Hybrid Search in Neo4j: Full-Text, Vectors, and Graph Topology with Cypher
Principal Database Product Manager at Neo4j
7 min read

Hybrid search in Neo4j can combine words, meaning, relationships, and structure in one retrieval pipeline.
As database engineers, we often talk about specific search indexes and ranking algorithms. But when we are building an application, we usually just want “search”. We want to find the right results. Whether those results came from lexical search, semantic search, structural similarity, or a combination of all three is usually an implementation detail.
In Neo4j, hybrid search is a Cypher pattern for combining results from multiple sources using re-ranking functions, our example we’ll use WRRF (Weighted Reciprocal Rank Fusion). The familiar version combines:
- lexical/full-text search to find exact names, acronyms, error codes, product names, API names, and domain terms
- semantic/vector search to find text that expresses similar meanings, even when it uses different words or languages.
This combination is often a straight upgrade to either approach in isolation. WRRF re-ranks the results, boosting results that appeared in more than one search.
But hybrid search in Neo4j doesn’t stop at combining one keyword and one vector search. You can combine results from multiple searches, perhaps several vector searches. Or even structural similarity search based on graph topology:
- structural/node embedding search to find nodes in the graph that occupy similar neighborhoods.
Once hybrid search has found the right starting points, the graph can also expand those results into connected context for GraphRAG. The flow can run the other way too: start with graph traversal to produce candidates, then use hybrid search to rank them.
The advantage of doing hybrid search in Neo4j is we can combine words, meaning, relationships, and structure in one retrieval pipeline.

Worked example: Support case investigation
Imagine a developer support team that wants to investigate support cases by finding related cases. A new case comes in: a customer saw a duplicate checkout charge after a payment request timed out and the client retried.
They do not yet know what kind of similarity will matter. The best related cases might use the same technical vocabulary, describe the same customer problem in different words, share the same graph context, or combine all three.
They have a knowledge graph with a model like this:

The complete Cypher for creating the graph, generating embeddings, indexing, and querying is linked at the end of the post.
Each search signal is useful, and incomplete
Each retrieval signal sees the support case from a different angle. Each one finds a useful result. Each one also finds noise.
Lexical search: same words
Full-text search is excellent when exact technical vocabulary matters. If a user searches for an API name, error code, configuration setting, or runbook title, exact words are often the strongest clue.
For the anchor case, a full-text query might include: Checkout API timeout retry idempotency key duplicate charge.
That finds a strong exact-vocabulary match: Idempotency key warning on checkout retry.
This is useful because it shares important terms with the anchor case: Checkout API, idempotency key, retry, and timeout.
But shared vocabulary is not the same as relevance. Full-text search can also find cases such as:
- Checkout timeout during inventory retry
- Duplicate webhook delivery after retry
- 429 rate-limit retry behavior
- Mobile cart duplicated item after offline retry
Those results are not random. They share words. But they are not the same operational issue.
Semantic search: same meaning
Semantic vector search solves a different problem. It can find cases that describe a similar situation using different words, or even a different language.
For example: Shopper billed twice after network drop.
This is a strong semantic match for a duplicate payment after a failed checkout retry, even though it does not need to use the exact terms idempotency key, Checkout API, or duplicate charge.
But semantic search also has its own kind of noise. It may retrieve cases such as:
- Subscriber billed twice after plan renewal
- Mobile cart duplicated item after offline retry
These are conceptually nearby. Depending on the application, they might even be useful. But they are not the same operational problem.
Structural search: same graph context
Structural search adds a graph-native signal. It asks whether two cases occupy similar neighborhoods in the graph.
A case such as: Unexpected refund workflow trigger, may not be the closest lexical or semantic match. But it becomes relevant if it is connected to the same payment API, duplicate-charge symptom, refund workflow, owning team, and duplicate-payment runbook.
That case is similar because of its relationships.
This is the kind of match a text-only retriever has to infer from prose. In Neo4j, if the relationships are already in the graph, topology can be turned into a retrieval signal.
Combining the signals
This is where hybrid search shines. For the support team, the best default search is not one of these modes. It is all three.

Re-ranking results
Once you have several ranked lists, the obvious next step is to combine them. But there is a trap: raw scores from different search systems do not usually mean the same thing.
A full-text score is not directly comparable to a vector similarity score. A semantic vector score is not necessarily comparable to a structural vector score. Even two vector indexes may have different score distributions if they use different embeddings, dimensions, or similarity functions.
So the support-case example uses weighted reciprocal rank fusion (WRRF).
Instead of comparing raw scores directly, each retrieval source contributes based on where a result appears in its ranked list. The weights let the application decide how much to trust each signal. In a support search application, exact technical vocabulary might deserve a stronger weight. In another domain, semantic similarity or structural similarity might matter more.
This lets us combine full-text, semantic, and structural search without pretending their raw scores are equivalent. The example also uses simple gates before fusion, such as minimum similarity thresholds and rules about whether a result must be top-ranked in one mode or corroborated by more than one signal.
The important pattern is:
- generate candidates from multiple retrieval signals
- preserve the rank from each signal
- apply lightweight quality gates
- fuse the ranked lists using weights
- use the graph to explain and expand the result
That pattern is more important than any one scoring formula.
Why Cypher is useful for real retrieval
It is possible to hide hybrid search behind a helper function, and for simple applications that can be a good starting point. But production retrieval often becomes application-specific very quickly. Teams usually need to tune behavior for their domain. They may need to boost exact technical matches, down-rank stale content, prefer records from a customer’s region, enforce security visibility, filter by product version, combine internal and external results, or expand retrieved entities into structured context for an LLM.
The query is not just glue code. It is the place where retrieval logic, graph logic, and product rules meet.
You can find a template for the hybrid search pattern in our developer guide.
Takeaways
Hybrid search in Neo4j is not limited to keyword search plus vector search.
It can combine:
- lexical search with full-text indexes
- semantic search with text embeddings and vector indexes
- structural search with graph-derived embeddings
- graph traversal to expand results into connected context
- Cypher logic for filters, boosts, gates, and product rules
The value of graph structure is not only that it gives you better context after search. It can help decide what should be found in the first place.
That is the difference Neo4j brings to hybrid search: retrieve by words, retrieve by meaning, retrieve by structure, and then return the connected context that explains why the result matters.
Complete worked example Cypher:
- Creating the sample support graph
- Generating semantic embeddings with the Neo4j GenAI plugin
- Generating structural embeddings with FastRP in Neo4j Graph Data Science
- Creating full-text and vector indexes
- Lexical/Full-text only
- Semantic/Vector only
- Structural/Node embedding only
- Hybrid search with WRRF results
Useful references:
- Neo4j hybrid search developer guide
- FastRP in Neo4j Graph Data Science
- Skills including Hybrid search for AI agents
Hybrid Search in Neo4j: Full-Text, Vectors, and Graph Topology with Cypher was originally published in Neo4j Developer Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.








