Hybrid Search¶
Uni provides hybrid search that combines vector similarity and full-text search using rank fusion algorithms. Get the best of both semantic understanding and keyword matching.
What It Provides¶
- Combined vector + FTS search in a single procedure.
- Reciprocal Rank Fusion (RRF) for robust result merging.
- Weighted fusion for tunable semantic vs keyword balance.
- Pre-filtering applied to both search branches.
- Individual score transparency when needed.
Example¶
use uni_db::Uni;
# async fn demo() -> Result<(), uni_db::UniError> {
let db = Uni::open("./my_db").build().await?;
let rows = db.query(r#"
CALL uni.search(
'Document',
{vector: 'embedding', fts: 'content'},
'neural network architectures',
null,
10
)
YIELD node, score, vector_score, fts_score
RETURN node.title, score, vector_score, fts_score
"#).await?;
println!("{:?}", rows);
# Ok(())
# }
Procedure Signature¶
CALL uni.search(label, properties, query_text [, query_vector] [, k] [, filter] [, options])
YIELD vid, score, node [, vector_score] [, fts_score]
Parameters:
| Parameter | Type | Description |
|---|---|---|
label |
String | Node label to search |
properties |
Map | {vector: 'prop1', fts: 'prop2'} |
query_text |
String | Text for FTS and auto-embedding |
query_vector |
List or null | Pre-computed vector (optional) |
k |
Integer | Number of results (default: 10) |
filter |
String | WHERE clause for pre-filtering |
options |
Map | Fusion options |
Fusion Options:
| Option | Values | Description |
|---|---|---|
method |
'rrf' (default), 'weighted' |
Fusion algorithm |
alpha |
0.0 - 1.0 | Vector weight for weighted fusion |
over_fetch |
Float | Over-fetch factor (default: 2.0) |
Fusion Methods¶
RRF (Reciprocal Rank Fusion) - Default¶
Best for general use. Combines rankings without requiring score normalization:
Weighted Fusion¶
Use when you want to tune the balance between semantic and keyword matching:
alpha = 0.7→ Favor semantic similarityalpha = 0.3→ Favor keyword matchingalpha = 0.5→ Equal weight (default)
Examples¶
With Pre-Filter¶
CALL uni.search(
'Document',
{vector: 'embedding', fts: 'content'},
'graph databases',
null,
10,
'category = "technology" AND year >= 2023'
)
YIELD node, score
RETURN node.title, score
Weighted Fusion (Favor Semantics)¶
CALL uni.search(
'Document',
{vector: 'embedding', fts: 'content'},
'deep learning',
null,
10,
null,
{method: 'weighted', alpha: 0.7}
)
YIELD node, score
RETURN node.title, score
Score Transparency¶
CALL uni.search(
'Document',
{vector: 'embedding', fts: 'content'},
'transformer models',
null,
10
)
YIELD node, score, vector_score, fts_score
RETURN node.title, score, vector_score, fts_score
Expression Form: similar_to¶
For scoring already-bound nodes (rather than top-K retrieval), use the similar_to() expression function. It works in WHERE, RETURN, ORDER BY, and Locy rule bodies:
-- Hybrid scoring as an expression
MATCH (d:Document)
RETURN d.title,
similar_to([d.embedding, d.content], 'machine learning') AS relevance
ORDER BY relevance DESC
LIMIT 20
-- With weighted fusion
MATCH (d:Document)
WHERE similar_to([d.embedding, d.content], 'deep learning',
{method: 'weighted', weights: [0.7, 0.3]}) > 0.5
RETURN d.title
similar_to uses the same fusion algorithms (RRF, weighted) as uni.search, but operates on one node at a time. See the Vector Search guide for full documentation.
Use Cases¶
- RAG applications: Combine semantic retrieval with keyword boosting.
- E-commerce search: Match product descriptions semantically while respecting exact brand/model queries.
- Document search: Find relevant documents even when terminology varies.
- Knowledge bases: Surface answers that are both semantically relevant and contain key terms.
When To Use¶
Use hybrid search when:
- Users might use different terminology than your content
- Some queries are keyword-specific (product names, codes) while others are conceptual
- You want robust search without tuning
- You need to combine the precision of keywords with the recall of semantics
Prerequisites¶
Hybrid search requires both:
- A vector index with embedding configuration
- A fulltext index on the text property
-- Vector index with auto-embed
CREATE VECTOR INDEX doc_embed FOR (d:Document) ON (d.embedding)
OPTIONS {
metric: 'cosine',
embedding: {provider: 'Candle', model: 'all-MiniLM-L6-v2', source: ['content']}
}
-- Fulltext index
CREATE FULLTEXT INDEX doc_fts FOR (d:Document) ON (d.content)
See also: Vector Search | Full-Text Search