Skip to content

Embedding Search Examples

Examples that show how embedding search works end-to-end, and which embedding field each API uses.

For full end-user docs, see:

  • Vector search guide: docs/user-guides/vector-search.md
  • Qdrant gRPC guide: docs/user-guides/qdrant-grpc.md

1) HTTP hybrid search (search.Service)

The HTTP search endpoint runs hybrid search (vector + BM25 with RRF fusion):

curl -X POST http://localhost:7474/nornicdb/search \
  -H "Content-Type: application/json" \
  -d '{
    "query": "machine learning algorithms",
    "limit": 10
  }'

Notes:

  • Query text is embedded server-side (when embeddings are enabled).
  • Results come from the indexed search path in pkg/search/search.go.

2) Cypher vector search (db.index.vector.queryNodes)

Cypher’s Neo4j-compatible vector procedure currently scans nodes in storage and computes similarity:

  • Implementation: pkg/cypher/call_vector.go
  • Storage access: storage.Engine.AllNodes()

String query (server-side embedding)

CALL db.index.vector.queryNodes('embeddings', 10, 'machine learning algorithms')
YIELD node, score
RETURN node, score
ORDER BY score DESC

Vector array query (client-side embedding)

CALL db.index.vector.queryNodes('embeddings', 10, [0.1, 0.2, 0.3, 0.4])
YIELD node, score
RETURN node, score
ORDER BY score DESC

Property vectors vs. internal embeddings

db.index.vector.queryNodes chooses embeddings in this order:

  1. node.NamedEmbeddings[index.property] (or "default" when no property is configured)
  2. node.Properties[index.property] (if it contains a vector array)
  3. node.ChunkEmbeddings[0..N] (best score across chunks)

That means Cypher can always work with property vectors, even if you never use NamedEmbeddings.

3) Qdrant gRPC named vectors (NamedEmbeddings)

The Qdrant gRPC endpoint stores vectors in Node.NamedEmbeddings:

  • Unnamed vector → NamedEmbeddings["default"]
  • Named vectors → NamedEmbeddings[name]

Example (Python qdrant-client, gRPC):

from qdrant_client import QdrantClient
from qdrant_client.http import models as m

client = QdrantClient(host="127.0.0.1", grpc_port=6334, prefer_grpc=True)

client.create_collection(
    collection_name="docs",
    vectors_config={
        "title": m.VectorParams(size=128, distance=m.Distance.COSINE),
        "content": m.VectorParams(size=128, distance=m.Distance.COSINE),
    },
)

client.upsert(
    collection_name="docs",
    points=[
        m.PointStruct(
            id="doc1",
            vector={"title": [1.0] * 128, "content": [0.2] * 128},
            payload={"kind": "article"},
        )
    ],
)

results = client.search(
    collection_name="docs",
    query_vector=("title", [1.0] * 128),
    limit=5,
)
print([r.id for r in results])

4) Graph + vector together (Cypher)

Vector similarity plus graph traversal is the “hybrid” capability you don’t get in a pure vector DB:

CALL db.index.vector.queryNodes('embeddings', 10, 'neural networks')
YIELD node, score
MATCH (node)-[:CITES]->(cited:Paper)
RETURN node, cited, score
ORDER BY score DESC

5) Mapping summary

  • Managed embeddings / chunked docsNode.ChunkEmbeddings
  • Qdrant vectors / named vectorsNode.NamedEmbeddings
  • Cypher property vectorsnode.Properties[index.property]