Skip to Content
We are live but in Staging 🎉

CRUD operations

Once you’ve created a collection, the day‑to‑day work is writing data (Create), changing it (Update), and removing it (Delete).

Dodil VBase is a vector database service (Milvus‑backed). In practice, “update” is implemented as an upsert: you write a new version of an entity using the same primary key.


Create: insert entities

Insert adds new entities (rows) to a collection.

Things to keep in mind:

  • Your payload must match the collection schema.
  • The primary key must be present for every entity.
  • Dense vector fields must have the correct dimension (e.g., 768) for every entity.
  • If your collection allows dynamic fields, you can add extra metadata keys beyond the declared schema.

Insert one entity

item = { "id": 1001, # primary key "text": "hello world", "embedding": [0.01, 0.02, 0.03, ...], # vector field "source": "docs", # (optional) dynamic field if enabled } res = vbase.insert( collection_name="my_collection", data=[item], ) print(res)

Insert many entities (batch)

Batch inserts are the common path for ingestion pipelines.

rows = [ {"id": 1001, "text": "a", "embedding": [0.1, 0.2, ...]}, {"id": 1002, "text": "b", "embedding": [0.2, 0.3, ...]}, {"id": 1003, "text": "c", "embedding": [0.3, 0.4, ...]}, ] res = vbase.insert( collection_name="my_collection", data=rows, ) print(res)

Common insert errors

  • Dimension mismatch: the vector length differs from the schema’s configured dimension.
  • Missing primary key: the entity doesn’t include the PK field.
  • Type mismatch: sending a string to a numeric field, etc.
  • Dynamic fields disabled: extra keys not in the schema are rejected.

Update: upsert entities

Vector databases typically don’t “edit a row in place” like a traditional SQL database. Instead, you upsert:

  • If the primary key doesn’t exist, the entity is inserted.
  • If the primary key does exist, the entity is replaced with the new version.

Upsert an entity (replace by primary key)

updated = { "id": 1001, "text": "hello world (v2)", "embedding": [0.011, 0.021, 0.031, ...], "source": "docs", } res = vbase.upsert( collection_name="my_collection", data=[updated], ) print(res)

Do I have to send all fields?

As a safe default, treat upsert as full replacement: send the full entity (including vector fields).

If you want partial updates (e.g., only change rating but keep the same vector), you generally have two options:

  1. Store frequently‑changing metadata in a separate system (KV / SQL), and keep the vector DB as the retrieval index.
  2. Use dynamic fields and re‑upsert the entity with the full payload you want to exist.

(Partial‑update semantics vary by engine/version; Dodil may expose a dedicated partial update helper when available.)


Delete: remove entities

Delete removes entities from a collection. You can delete:

  • By primary keys (best when you already know the IDs)
  • By filter expression (best when deleting a class of entities)

Delete by primary keys

res = vbase.delete( collection_name="my_collection", ids=[1001, 1002], ) print(res)

Delete by filter

Filters are useful when you want to remove many entities at once.

res = vbase.delete( collection_name="my_collection", filter="source in ['docs', 'web']", ) print(res)

Delete by filter + partition (optional)

If you use partitions, you can scope deletion to a single partition.

res = vbase.delete( collection_name="my_collection", filter="source == 'docs'", partition_name="partitionA", ) print(res)

Operational notes

  • Consistency: inserts/upserts become searchable once the system has processed the writes. If you’re running tests immediately after writing, you may need to wait briefly (or follow your environment’s recommended load/index steps).
  • Idempotency: designing your primary keys deterministically (e.g., a stable document chunk ID) makes retries safe.

Next steps

  • Learn about filtering and search queries
  • Learn how indexing and load/release affect performance
Last updated on