Closing the Search Gap
with Milvus 3.0

Faster, cheaper and easier hybrid semantic / full-text search

Aug 19 · 2026

Simon Hearne
Solutions Architect · Zilliz

The search gap

Semantic search and full-text search grew up in different engines. This meant compromising somewhere, until now. Milvus is one engine that is genuinely good at both:

two engines

application
exact semantic
ElasticsearchBM25 · text score
vector DBANN · vector score

sync writes ↔ reconcile scores

Two clusters, two scoring models, two write paths and complex fusion logic.

just use elasticsearch

application
exactsemantic
ElasticsearchBM25 + dense_vector kNN

one engine · vectors bolted on

RAM-bound HNSW, re-shard to grow. Orfium capped at ~500K references; Rexera cut cost 50% on the way out.

milvus 3.0

application
exactsemantic
MilvusBM25 + vectors · one ranked result

one call · nothing to reconcile

One schema, one query, one cluster. Hybrid ranking runs inside the kernel, not in your app tier.

Who hits this gap

BM25 + Vector search is greater than the sum of its parts.

RAG / AI agents

exactcreate_index() · v2.6.4 · config flags
semantic"how do I make ingestion faster?"

Legal & compliance

exact§230(c)(1) - document-specific
semantic"documents about indemnification"

Observability

exactconnection reset by peer, verbatim
semantic"incidents like this one"

E-commerce

exactSKU34632A · brand names
semantic"comfy red shoes for work in an office"

A decade dedicated to retrieval

2017Zilliz founded by ex-Oracle Cloud DB engineer
2019Milvus open-sourced by Zilliz
2021Milvus 1.0 graduates the LF AI & Data Foundation
2022Milvus 2.0: cloud-native re-architecture
2025Milvus 2.5: full-text search native support
2026Milvus 3.0: the search gap closes


GitHub stars45k+

github.com/milvus-io/milvus

Docker pulls100M+

deployments in the wild

Enterprise users10,000+

running Milvus in production

logo wall

Running in production today

Teams that collapsed a two-engine stack onto Milvus:

OpenSearchZilliz Cloud

123RFimage search

200M+ stock-asset vectors: infra cost cut >50%, latency halved to sub-50ms

OpenSearchZilliz Cloud

Plaudagent memory

10B+ agent-memory chunks per region at <200ms average recall, across 2M+ devices

ElasticsearchZilliz Cloud

RexeraRAG + agents

Hybrid search: retrieval accuracy +40%, cost −50% vs Elasticsearch

ElasticsearchZilliz Cloud

Orfiumaudio matching

~250M audio vectors; the old ES setup maxed out at ~500K references

ElasticsearchMilvus

OpusSearchhybrid search

One deployment for semantic + BM25 exact match across 170M+ videos

ElasticsearchZilliz Cloud

OpenArtmultimodal search

456M vectors moved with no re-embedding: P99 25s → 300ms, compute cost −85%

Key search features in Milvus

Full-text

  • BM25 scoring 2.5+
  • Analyzers & synonyms 2.5+
  • Custom dictionaries 3.0
  • Multilingual auto-detect 2.5+
  • Highlighting 2.6+
  • Phrase matching 2.6+

Search

  • Hybrid + RRF 2.4+
  • Grouping 3.0
  • Aggregations 3.0
  • Relevance shaping 2.6+
  • Geo filtering 2.6+
  • TIMESTAMPTZ dates 2.6+

Efficiency

  • RaBitQ 1-bit quant. 2.6+
  • SQ8 refinement 2.6+
  • SINDI sparse retrieval 3.0
  • 3× smaller BM25 index 3.0
  • Loon storage engine 3.0

Schema

  • Nullable scalars 2.5+
  • Nullable vectors 2.6+
  • Dynamic fields 2.2
  • JSON path indexes 2.5+
  • JSON shredding 2.6+

Schema flexibility

Elasticsearch's structural advantage was letting documents be messy. Milvus 3.0 closes that gap too:

missing data

Nullable fields

Scalars and vectors can be null: no sentinel values skewing filters, no dummy embeddings poisoning distance math, no splitting collections when some docs lack an image

vs ES: documents omit fields freely, and that blocked migrations of sparse real-world data. It now moves over as-is

rich metadata

JSON shredding + indexing

Nested JSON shreds into typed columns with path indexes: filters on meta["brand"] run at columnar speed, not per-row blob parsing

vs ES: dynamic mapping indexes every key, but risks mapping explosion, reindex req'd to change a type. Milvus keeps the schema stable

evolving payloads

Dynamic schema

Insert fields you never declared: they land in a hidden JSON field, still filterable and indexable. Payloads evolve with zero migrations, zero downtime

vs ES: schemaless writes are supported in ES but mappings are required to make fields searchable. Milvus improves on this

Faster, cheaper, easier

Cloud-native high performance architecture for ANN, benefits BM25:

Faster

Kernel-side execution

Search, filter, group and aggregate run inside the vector kernel: no shipping candidates to the app tier for post-processing

Cheaper

10× lower memory

RaBitQ 1-bit primary index + SQ8 refinement, at equal recall. Smaller BM25 indices. No Java overhead. No replica requirement. Tiered-storage optional.

Easier

One engine

One schema, hybrid search in a single call: no sync, no score reconciliation. All core features in F/OSS license.

The test lab: a fair comparison

  • Milvus 3.0 standalone vs Elasticsearch 9.4 on Docker, both capped at 8 GB / 4 CPU
  • Same ~100k Amazon-review docs, loaded byte-identically from one Parquet
  • Same 1024-d COSINE FP32 vectors: no re-embedding, the same floats both sides
  • Same BM25 analyzer chain (standard + english stem/stop)
  • The demo app's Introduction tab verifies all of this live against the running containers
  • Open source for community validation

What's next

If you rely on these in Elasticsearch, they're on the way:

fuzzinesscoming

Typo-tolerant search

Fast, fuzzy BM25 matching with prefix pruning, so typos still find the right results

phrase_prefixcoming

Search-as-you-type

Phrase-prefix matching for typeahead and autocomplete

rescorecoming

Multi-stage reranking

Shape relevance in stages, beyond function_score

bloomcoming

Filters at scale

Bloom-filter support and per-element array matching replace giant OR-chains

Safe harbour

These are forward-looking features, not currently available.

Run it yourself

github.com/simonhearne/milvus_es_lab

docker compose up -d
python data/fetch.py # one Parquet, ~370 MB
docker compose exec demo python data/load_milvus.py
docker compose exec demo python data/load_es.py
docker compose exec demo python data/load_multilingual.py

Requires Docker with ≧16 GB RAM

Everything I showed you is reproducible on your laptop.

Next up!

Join me in two weeks to walk through the migration process to Milvus 3.0.

zilliz.com/event/migrating-from-elasticsearch-opensearch-to-milvus

next webinar image

You could be running a proof of concept in under an hour!

Thank you!

Questions?

simon @ zilliz.com

Simon Hearne
Solutions Architect · Zilliz