Vector search
ShrikeDB stores embeddings in named indexes and returns their entity identifiers through streaming, packed, batch, and Cypher query surfaces. Use the same entity ID for a vector, graph node, and key-value record to move from similarity search to connected context and application payloads.
How vector data is organized
Every vector belongs to an index name and an entity ID. An optional schema ID provides another namespace boundary. The vector dimension and distance metric must remain consistent for an index.
| Value | Purpose | Example |
|---|---|---|
Index name |
Separates embeddings by model and use case. |
|
Entity ID |
Joins a search result to graph and KV data. |
The UID used for the corresponding graph node |
Schema ID |
Selects a schema-scoped vector partition when the deployment uses one. |
Application or tenant schema identifier |
Vector |
Ordered floating-point embedding generated by the selected model. |
A 384- or 768-dimensional array |
|
Maximum nearest neighbors requested. |
|
|
HNSW search breadth. Larger values generally examine more candidates. |
|
Name indexes after the embedding source and model version. Model upgrades usually change the vector space, so load the new embeddings into a new index instead of mixing them with the prior model.
Try vectors in ShrikeDB Cloud
Open ShrikeDB Cloud, sign in, and choose Vectors. Upload a JSONL file with one record per line:
{"entity_id":"10042","vector":[0.18,-0.04,0.61,0.22]}
{"entity_id":"10043","vector":[0.20,-0.03,0.58,0.19]}
Name the index, inspect its row count and dimension, and load it. Enter a query vector to see nearest entity IDs and scores. Open in Cypher carries the query into the editor, where you can add graph patterns. Query a graph node in the Query view, copy its UID, and use that decimal string as entity_id when you want a vector hit to bind to the node. The Cloud Query view requests UIDs as strings to preserve all 64 bits in the browser. Each named index keeps one fixed dimension; different indexes may use different dimensions.
Cloud also exposes authenticated POST /api/v1/vector/insert, POST /api/v1/vector/search, and GET /api/v1/vector/indexes. The public HTTP workflow shows requests with a tenant API key. The free workspace admits batches of at most 256 vectors and 2 MiB per request within its storage budget.
Insert vectors with gRPC
InsertVector writes one vector. BulkInsertVectors amortizes request overhead for loaders and returns the accepted count.
grpcurl -plaintext \
-import-path ./proto \
-proto shrikedb.v2.proto \
-d '{
"indexName": "incident_text_v3",
"entityId": {"value": "10042"},
"vector": [0.18, -0.04, 0.61, 0.22]
}' \
127.0.0.1:50051 \
shrikedb.v2.ShrikeDbService/InsertVector
For a batch:
grpcurl -plaintext \
-import-path ./proto \
-proto shrikedb.v2.proto \
-d '{
"indexName": "incident_text_v3",
"vectors": [
{"entityId": {"value": "10042"}, "vector": [0.18, -0.04, 0.61, 0.22]},
{"entityId": {"value": "10043"}, "vector": [0.20, -0.03, 0.58, 0.19]}
]
}' \
127.0.0.1:50051 \
shrikedb.v2.ShrikeDbService/BulkInsertVectors
Production connections may require TLS, bearer metadata, and a database selector. Follow Connect To ShrikeDB for connection settings.
Search through the vector API
| RPC | Response | Use |
|---|---|---|
|
A stream of |
Consume results incrementally. |
|
Parallel arrays of entity IDs and scores |
Reduce protobuf framing and allocation overhead. |
|
One packed result for each query vector |
Submit multiple independent searches in one request. |
grpcurl -plaintext \
-import-path ./proto \
-proto shrikedb.v2.proto \
-d '{
"indexName": "incident_text_v3",
"queryVector": [0.17, -0.02, 0.60, 0.24],
"k": 20,
"efSearch": 200
}' \
127.0.0.1:50051 \
shrikedb.v2.ShrikeDbService/VectorSearchPacked
snapshot_version pins a search to a published database snapshot when the caller already has that version. VectorFilter.entity_ids restricts candidates to a supplied UID set. Use filters when the allowed population is already known; use a Cypher graph pattern when graph structure defines the population.
Search inside Cypher
vector.knn makes vector results part of a Cypher row pipeline:
CALL vector.knn(
"incident_text_v3",
[0.17, -0.02, 0.60, 0.24],
40,
{ef: 200}
)
YIELD node AS incident, score
RETURN incident, score
LIMIT 20
The index name and k are literals in this execution path. The query vector
can be a literal or a request parameter. The procedure yields the matching
node UID and its metric score.
Use k as the candidate budget and LIMIT as the final result budget. When graph or property predicates remove candidates after the vector stage, request enough candidates to leave a useful final set.
Join vector results to graph context
A vector result is a UID. Bind that UID to a graph node and continue with an ordinary pattern:
CALL vector.knn("incident_text_v3", $query_embedding, 100, {ef: 256})
YIELD node AS incident, score
MATCH (incident:Incident)-[:INVOLVES]->(asset:Asset)
RETURN incident, asset, score
LIMIT 25
This retrieves vector candidates first, then follows a directed relationship for each candidate. Use the same UID for the vector entry and graph node. See Multimodal and hybrid queries for a complete mixed query.
Hydrate final results from KV
Keep large documents or opaque application payloads in KV and fetch them after narrowing the result:
CALL vector.knn("incident_text_v3", $query_embedding, 50, {ef: 200})
YIELD node AS incident, score
MATCH (incident:Incident)-[:INVOLVES]->(asset:Asset)
CALL kv.get("default", incident) YIELD value AS incident_json
RETURN incident, asset, score, incident_json
LIMIT 20
The first kv.get argument names the public KV namespace. PutKeyValue
writes to default; use the incident UID as its key. KV reads occur after the
graph expansion and final row limit.
Choose search parameters
Begin with a representative evaluation set whose relevant neighbors are known. Record recall at the required k, median latency, p95 latency, index size, ingestion rate, and concurrency. Then change one parameter at a time.
-
Increase
ef_searchwhen recall is insufficient and the latency budget permits more exploration. -
Increase
kwhen downstream graph or metadata filters leave too few rows. -
Keep
kclose to the application requirement for unfiltered nearest-neighbor requests. -
Use packed and batch-packed RPCs when response framing dominates many small requests.
-
Separate model versions into named indexes and compare them with the same relevance set.
For partitioned HNSW searches, ef_search controls exploration within the partitions selected for a query. Increasing it cannot recover neighbors in partitions that were skipped. The standard ANN route searches all partitions unless an operator sets a partition budget or starts the server with SHRIKEDB_HNSW_EXPERIMENTAL_SEMANTIC_SHORTLIST=1. Calibrate any shorter route against an exhaustive sample from the same embedding model before using its throughput figure as a quality-matched comparison.
Search scores only have meaning in the metric and embedding space used by that index. Do not compare raw scores from unrelated models as if they shared a scale.
Durability and restart behavior
Acknowledged vectors are part of durable database state. Small partitions and newly acknowledged entries can remain in a pending search buffer while HNSW construction proceeds; shutdown persists that state and recovery restores search visibility. Keep the entire configured data directory on persistent storage and use the normal server shutdown path.
Named indexes are scoped independently. Reusing an entity UID in two index names does not merge their vectors. Schema IDs and embedding model metadata provide further partition identity. Use the vector namespace health report when diagnosing a missing or unexpectedly empty index.
Inspect and troubleshoot a search
| Symptom | Check |
|---|---|
No results |
Index name, schema/database scope, vector dimension, recovered namespace inventory, and any entity filter. |
Unexpected neighbors |
Embedding normalization, model version, metric, query preprocessing, and recall against an exhaustive sample. |
Too few rows after a graph join |
Increase vector candidate |
Latency grows with a new setting |
Compare |
Results differ after restart |
Confirm the same data directory and database selection, then inspect vector recovery and namespace health. |
Use PROFILE for a Cypher composition and server vector traces for direct vector RPCs. Record planning, vector search, graph expansion, KV hydration, and result delivery separately.
Related documentation
-
Multimodal and hybrid queries for graph, vector, KV, RDF, and SpaceKey composition.
-
Improve query performance for measurement and plan tuning.
-
Observability for traces and health reports.
-
Back up and restore a standalone database for durable data handling.
-
gRPC API for request and response definitions.