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:
- Store frequently‑changing metadata in a separate system (KV / SQL), and keep the vector DB as the retrieval index.
- 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