Vector Search
Find semantically similar nodes using nearest-neighbor search over embeddings.
Vector search finds nodes that are semantically similar to a query vector. It
uses the current Omnigraph vector index implementation. An ivf_flat index
with L2 distance. Over a Vector(N) field.
Schema setup
Declare a Vector(N) property with @index to enable vector search. N is
the embedding dimension.
node Person {
name: String @key
bio: String @index
embedding: Vector(1536) @index
}
node Document {
title: String @key
content: String
embedding: Vector(768) @index
}The @index annotation on a Vector(N) field causes Omnigraph to build the
current vector index for that column. Without it, nearest() queries on that
field are rejected at compile time.
If you want embeddings to be auto-generated from another field, use
@embed(source_property):
node Person {
name: String @key
bio: String @index
embedding: Vector(1536) @embed(bio) @index
}nearest(). Vector similarity ranking
nearest(field, query) appears in the order block and ranks results by
nearest-neighbor distance to the query. The query argument can be either a
Vector(N) parameter or a String. When you pass a string, the engine
auto-embeds it using the configured runtime embedding client, so callers
don't need their own embedding pipeline. Because nearest() requires a
limit clause, pair them together.
query similar_people($vec: Vector(1536)) {
match {
$p: Person
}
return { $p.name, $p.bio }
order { nearest($p.embedding, $vec) }
limit 10
}Searching by string (auto-embed)
Pass a string in place of a vector and the engine embeds it for you:
query similar_people_by_text($q: String) {
match {
$p: Person
}
return { $p.name, $p.bio }
order { nearest($p.embedding, $q) }
limit 10
}omnigraph read --uri ./graph.omni \
--query queries.gq \
--name similar_people_by_text \
--params '{"q": "machine learning researcher in NYC"}'This is the most common shape in agent code: you have natural language, you want nearest neighbors, you don't want to maintain a separate embed step.
Passing vector parameters
If you already have an embedding vector. For example, because you computed it
inside the agent. Pass it as a JSON array in --params:
omnigraph read --uri ./graph.omni \
--query queries.gq \
--name similar_people \
--params '{"vec": [0.021, -0.003, 0.118]}'In practice, you generate the query vector from an embedding model and pass it as a parameter.
Via the HTTP API:
curl -X POST http://localhost:8080/read \
-H "Content-Type: application/json" \
-d '{
"query_source": "query similar_people($vec: Vector(1536)) { match { $p: Person } return { $p.name, $p.bio } order { nearest($p.embedding, $vec) } limit 10 }",
"query_name": "similar_people",
"params": {"vec": [0.021, -0.003, 0.118]},
"branch": "main"
}'Filtering before ranking
Combine a match filter with nearest() in order to narrow the candidate
set before ranking.
query similar_active_people($vec: Vector(1536)) {
match {
$p: Person { status: "active" }
}
return { $p.name, $p.bio }
order { nearest($p.embedding, $vec) }
limit 10
}This first filters to active people, then ranks the filtered set by vector similarity.
Combining with traversal
Vector search composes with graph traversal. You can find semantically similar nodes and then follow edges to related entities:
query similar_people_at_company($vec: Vector(1536), $company: String) {
match {
$p: Person
$p worksAt $c: Company { name: $company }
}
return { $p.name, $p.bio, $c.name }
order { nearest($p.embedding, $vec) }
limit 10
}This finds people who work at a specific company, ranked by how similar their embedding is to the query vector.