Part 2 · The Harness Around the Model

Hands-on Milvus

Connect, create, batch insert, index, search, query, and delete

THE QUESTION THIS PAGE ANSWERS

ANSWER FIRST

What is the key idea behind “Hands-on Milvus”?

Connect, create, batch insert, index, search, query, and delete

DECISION RULE

Make the claim earn its place. Use this page as a decision aid, not a definition to memorize. Connect the idea to one real task, one observable result, and one failure that would change your mind.

TRY NEXT

Write one question you could answer with evidence after trying this idea.

WATCH FOR

A conclusion that sounds complete but leaves the key assumption untested.

Start the service with the official Docker Standalone guide, then install pymilvus and sentence-transformers. The dimension is derived from actual model output—no random vectors posing as semantic search.
Connect, define, and batch insert
from pymilvus import MilvusClient, DataType
from sentence_transformers import SentenceTransformer
COLLECTION = "support_kb"
client = MilvusClient(uri="http://localhost:19530")
print(client.list_collections())  # Verify connectivity; health is commonly exposed at 9091/healthz
RESET_LAB = False  # Set True only after confirming old lab data is disposable
if client.has_collection(collection_name=COLLECTION):
    if not RESET_LAB:
        raise RuntimeError("support_kb exists; rename it or explicitly enable RESET_LAB")
    client.drop_collection(collection_name=COLLECTION)  # Deletes the whole collection
encoder = SentenceTransformer("BAAI/bge-m3")
docs = [{"id": 1, "text": "Refunds arrive within three business days", "category": "refund"},
        {"id": 2, "text": "Sign in again after changing your password", "category": "account"}]
vectors = encoder.encode([d["text"] for d in docs], normalize_embeddings=True).tolist()
schema = MilvusClient.create_schema(auto_id=False, enable_dynamic_field=False)
schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True)
schema.add_field(field_name="vector", datatype=DataType.FLOAT_VECTOR, dim=len(vectors[0]))
schema.add_field(field_name="text", datatype=DataType.VARCHAR, max_length=1000)
schema.add_field(field_name="category", datatype=DataType.VARCHAR, max_length=64)
client.create_collection(collection_name=COLLECTION, schema=schema)
client.insert(collection_name=COLLECTION, data=[{**d, "vector": v} for d, v in zip(docs, vectors)])
Index, load, and filtered Top-K search
index = client.prepare_index_params()
index.add_index(field_name="vector", index_type="HNSW", metric_type="COSINE",
                params={"M": 16, "efConstruction": 200})
client.create_index(collection_name=COLLECTION, index_params=index)
client.load_collection(collection_name=COLLECTION)
query_vector = encoder.encode(["When will my refund arrive?"], normalize_embeddings=True).tolist()
hits = client.search(collection_name=COLLECTION, data=query_vector, anns_field="vector", limit=3,
    filter='category == "refund"', output_fields=["text", "category"],
    search_params={"metric_type": "COSINE", "params": {"ef": 64}})
Query and delete
rows = client.query(collection_name=COLLECTION, filter='category == "account"', output_fields=["id", "text"])
client.delete(collection_name=COLLECTION, filter="id == 2")
# Destructive; use only in a disposable lab:
# client.drop_collection(collection_name=COLLECTION)

Writes

Insert in batches; use stable IDs plus upsert or application deduplication for idempotency—insert alone does not deduplicate. Record content, embedding-model, and model-version metadata.

Deletes

For reversible deletion, mark active=false first. Physical deletes reclaim storage later through Compaction.

Checklist Same model, dimension, and COSINE metric; real embeddings; load before search. Use FLAT as a small-scale correctness baseline before tuning HNSW.

Why “Connect, define, and batch insert” can find relevant content

“Insert in batches;” moves retrieval beyond storing material: the real question is how to find what is relevant. That decision shapes the input quality of RAG, recommendation, and image-search systems.

Similarity is not the answer

In the flow described by “For reversible deletion, mark active=false first.”, embeddings place items in a comparable semantic space and a neighbor index narrows the search. The final answer still depends on whether the retrieved chunks cover the question, whether the distance metric fits, and whether the evidence is current.

Separate findable from relevant

Turn “For reversible deletion, mark active=false first.” into a small test: prepare queries with known answers, record relevance, misses, and distractors, then decide whether chunking, the index, or reranking needs to change.

“Connect, define, and batch insert” grounds the problem in “from pymilvus import MilvusClient, DataType from sentence_transformers import SentenceTransformer COLLECTION = "support_kb" client = MilvusClient(uri= "http://localhost:19530" ) print(client.list_collections())…”. “Index, load, and filtered Top-K search” then moves it toward “index = client.prepare_index_params() index.add_index(field_name= "vector" , index_type= "HNSW" , metric_type= "COSINE" , params={ "M" : 16, "efConstruction" : 200}) client.create_index(collection_name=COLLECTI…”. Together, they show that the lesson is not just a conclusion to remember, but a claim with conditions.

Carry the judgment into the next situation

The same logic applies to retrieval: define what counts as relevant, check whether recall covers the question, and then inspect whether ranking, chunking, or freshness pushed useful evidence out.

  • “Connect, define, and batch insert”: from pymilvus import MilvusClient, DataType from sentence_transformers import SentenceTransformer COLLECTION = "support_kb" client = MilvusClient(uri= "http://localhost:19530" ) print(client.list_collections())…
  • “Index, load, and filtered Top-K search”: index = client.prepare_index_params() index.add_index(field_name= "vector" , index_type= "HNSW" , metric_type= "COSINE" , params={ "M" : 16, "efConstruction" : 200}) client.create_index(collection_name=COLLECTI…
  • “The closing point”: For reversible deletion, mark active=false first. Physical deletes reclaim storage later through Compaction

The final “The closing point” brings the discussion to “For reversible deletion, mark active=false first. Physical deletes reclaim storage later through Compaction”. The useful thing to carry forward is knowing which judgments must be revisited when input, scale, or risk changes.

Mark as learned Your reading progress updates automatically
← PreviousNext →

Keep reading

The next useful article in the thread.

ARTICLE DISCUSSION

Leave one useful thought here.

Keep the idea that clicked, the question that stayed open, or a small note for the next learner.

Discussing Hands-on Milvus The Harness Around the Model
3discussionsArticle discussion · synced with the Circle
View in the learning circle
AM
Asha MorganContent editor
INSIGHTField note

I turned one judgment from this article into a small experiment I could run today. Knowing what to observe next is more useful than simply remembering the conclusion.

ARTICLE DISCUSSION7 helpful
LH
Lin HarperIndie developer
INSIGHTInsight

After reading this, I first looked for the conditions behind the idea instead of copying the method into a project. That order made the later trade-offs much clearer.

ARTICLE DISCUSSION5 helpful
KM
Kiki MooreProduct operations
QUESTIONQuestion

When this judgment reaches real work, which constraint should be added first? I am curious which step matters most between reading and the first practical attempt.

ARTICLE DISCUSSION4 helpful