Hybrid Search
Hybrid search combines full-text and vector search to leverage both keyword matching and semantic understanding. This provides more accurate and relevant results by merging the strengths of both search modes.
Basic Hybrid Search
To perform hybrid search, set the mode to 'hybrid' and provide both a search term and a vector:
import { create , insert , search , MODE_HYBRID_SEARCH } from '@orama/orama'
const db = create ({
schema: {
title: 'string' ,
description: 'string' ,
embedding: 'vector[1536]'
}
})
insert ( db , {
title: 'Noise cancelling headphones' ,
description: 'Best noise cancelling headphones on the market' ,
embedding: [ 0.2432 , 0.9431 , 0.5322 , ... ] // 1536 dimensions
})
const results = search ( db , {
mode: MODE_HYBRID_SEARCH ,
term: 'Noise cancelling headphones' ,
vector: {
value: [ 0.1 , 0.2 , 0.3 , ... ],
property: 'embedding'
}
})
How Hybrid Search Works
Hybrid search performs both full-text and vector searches, then merges and ranks the results:
Full-Text Search
Orama performs a BM25-based full-text search on string properties
Vector Search
Simultaneously performs vector similarity search on the specified embedding property
Score Normalization
Normalizes scores from both searches using min-max normalization
Result Merging
Combines results using weighted scoring based on hybrid weights
Final Ranking
Returns merged results sorted by hybrid score
Search Parameters
term (Required)
The search term for full-text search:
const results = search ( db , {
mode: 'hybrid' ,
term: 'Noise cancelling headphones' ,
vector: {
value: embeddings ,
property: 'embedding'
}
})
Unlike vector search, term is required for hybrid search.
vector
The vector configuration for semantic search:
const results = search ( db , {
mode: 'hybrid' ,
term: 'headphones' ,
vector: {
value: [ 0.1 , 0.2 , 0.3 , ... ],
property: 'embedding'
}
})
vector.value
number[] | Float32Array
required
The embedding vector to search with
The schema property containing embeddings
hybridWeights
Control the importance of full-text vs vector search results:
const results = search ( db , {
mode: 'hybrid' ,
term: 'headphones' ,
vector: {
value: embeddings ,
property: 'embedding'
},
hybridWeights: {
text: 0.7 , // 70% weight to full-text search
vector: 0.3 // 30% weight to vector search
}
})
Weight for full-text search results (0-1). Higher values prioritize keyword matches.
Weight for vector search results (0-1). Higher values prioritize semantic similarity.
By default, Orama uses equal weights (0.5/0.5) for both search modes. The weights should sum to 1.0.
properties
Specify which properties to search for full-text search:
const results = search ( db , {
mode: 'hybrid' ,
term: 'headphones' ,
properties: [ 'title' , 'description' ], // Only search these fields
vector: {
value: embeddings ,
property: 'embedding'
}
})
similarity
Set the minimum similarity threshold for vector search:
const results = search ( db , {
mode: 'hybrid' ,
term: 'headphones' ,
vector: {
value: embeddings ,
property: 'embedding'
},
similarity: 0.8 // Default: 0.8
})
limit and offset
Control pagination of hybrid search results:
const results = search ( db , {
mode: 'hybrid' ,
term: 'headphones' ,
vector: {
value: embeddings ,
property: 'embedding'
},
limit: 10 , // Return 10 results (default: 10)
offset: 0 // Skip first 0 results (default: 0)
})
tolerance
Set typo tolerance for full-text search:
const results = search ( db , {
mode: 'hybrid' ,
term: 'hedphones' , // Typo
vector: {
value: embeddings ,
property: 'embedding'
},
tolerance: 1 // Allow 1 character difference
})
threshold
Set the threshold for full-text search term matching:
const results = search ( db , {
mode: 'hybrid' ,
term: 'Red Headphones' ,
vector: {
value: embeddings ,
property: 'embedding'
},
threshold: 1 // Default: 1
})
threshold: 0 - Return documents containing ALL search terms
threshold: 1 - Return documents containing ANY search term
Advanced Features
Field Boosting
Give more importance to specific fields in full-text search:
const results = search ( db , {
mode: 'hybrid' ,
term: 'headphones' ,
properties: [ 'title' , 'description' ],
boost: {
title: 2 // Title matches are 2x more important
},
vector: {
value: embeddings ,
property: 'embedding'
}
})
BM25 Relevance Tuning
Customize BM25 parameters for full-text search:
const results = search ( db , {
mode: 'hybrid' ,
term: 'headphones' ,
relevance: {
k: 1.2 ,
b: 0.75 ,
d: 0.5
},
vector: {
value: embeddings ,
property: 'embedding'
}
})
Including Vectors in Response
Control whether to include embeddings in the response:
const results = search ( db , {
mode: 'hybrid' ,
term: 'headphones' ,
vector: {
value: embeddings ,
property: 'embedding'
},
includeVectors: false // Default: false
})
Vectors can be very large (1536+ dimensions). Only set includeVectors: true if you need the actual embedding values in the response.
Combining with Filters and Facets
With Filters
const results = search ( db , {
mode: 'hybrid' ,
term: 'headphones' ,
vector: {
value: embeddings ,
property: 'embedding'
},
where: {
price: {
lt: 100
},
category: 'electronics'
}
})
With Facets
const results = search ( db , {
mode: 'hybrid' ,
term: 'headphones' ,
vector: {
value: embeddings ,
property: 'embedding'
},
facets: {
'category' : {
limit: 10 ,
sort: 'DESC'
}
}
})
With Grouping
const results = search ( db , {
mode: 'hybrid' ,
term: 'headphones' ,
vector: {
value: embeddings ,
property: 'embedding'
},
groupBy: {
properties: [ 'category' ],
maxResult: 5
}
})
Using with Plugins
Secure Proxy Plugin
Automatically generate embeddings at search time:
import { pluginSecureProxy } from '@orama/plugin-secure-proxy'
const db = create ({
schema: {
title: 'string' ,
embedding: 'vector[1536]'
},
plugins: [
await pluginSecureProxy ({
apiKey: 'your-api-key' ,
defaultProperty: 'embedding'
})
]
})
// Plugin generates embeddings automatically
const results = search ( db , {
mode: 'hybrid' ,
term: 'Noise cancelling headphones'
// No need to provide vector - plugin handles it
})
Embeddings Plugin
Generate embeddings at insert and search time:
import { pluginEmbeddings } from '@orama/plugin-embeddings'
import '@tensorflow/tfjs-node'
const plugin = await pluginEmbeddings ({
embeddings: {
defaultProperty: 'embeddings' ,
onInsert: {
generate: true ,
properties: [ 'title' , 'description' ]
}
}
})
const db = create ({
schema: {
title: 'string' ,
description: 'string' ,
embeddings: 'vector[512]'
},
plugins: [ plugin ]
})
const results = await search ( db , {
term: 'Headphones' ,
mode: 'hybrid'
})
Adjust Hybrid Weights
If you know your use case favors keywords or semantics, adjust the weights: // Keyword-heavy queries
hybridWeights : { text : 0.8 , vector : 0.2 }
// Semantic-heavy queries
hybridWeights : { text : 0.2 , vector : 0.8 }
Limit Result Count
Hybrid search is more expensive than single-mode search: search ( db , { mode: 'hybrid' , term: '...' , limit: 10 })
Use Property Filtering
Limit full-text search to specific properties: search ( db , {
mode: 'hybrid' ,
properties: [ 'title' ], // Faster than all properties
term: '...'
})
Optimize Vector Dimensions
Smaller embeddings (384-512) are faster than larger ones (1536+)
Use Cases
E-commerce Search Combine product name matching with semantic understanding of descriptions
Documentation Search Match exact terms while understanding user intent and context
Content Discovery Find related content through both keywords and semantic similarity
Support Tickets Match keywords while understanding similar issues semantically
Full-Text Search Learn about full-text search capabilities
Vector Search Understand vector similarity search
Filters Filter hybrid search results
Boosting Boost specific fields in hybrid search