How it works
1
Indexing
Each document’s text is passed through a SentenceTransformers model (
SentenceTransformersDocumentEmbedder) to produce a dense float vector. The vector and document metadata are stored in the target vector database.2
Query embedding
At search time, the query string is embedded with the same model (
SentenceTransformersTextEmbedder) to produce a query vector.3
Nearest-neighbor retrieval
The database performs approximate nearest-neighbor (ANN) search over indexed embeddings and returns the top-k most similar documents ranked by cosine similarity score.
4
Optional filtering
Metadata filters can be applied to restrict the candidate set before similarity scoring, using the backend’s native filter syntax.
EmbedderFactory (from utils/embeddings.py) creates and warms up both the document and text embedders from the config file. Warm-up pre-loads the model weights so the first real call does not incur cold-start latency.
Indexing pipeline example
src/vectordb/haystack/semantic_search/indexing/chroma.py
Search pipeline example
src/vectordb/haystack/semantic_search/search/chroma.py
Configuration
Each backend has config files underconfigs/. A typical config:
When to use it
Natural-language questions where phrasing in the question may differ from phrasing in documents
General-purpose RAG starting points before specializing with advanced features
Any corpus where exact keyword overlap between query and documents is unreliable
When not to use it
Settings to tune first
Common pitfalls
Supported backends
Chroma, Milvus, Pinecone, Qdrant, Weaviate. Each backend has an indexing script inindexing/ and a search script in search/.
Dataset configs provided
ARC, Earnings Calls, FActScore, PopQA, TriviaQA. Config files are named{backend}_{dataset}.yaml inside configs/.
Next steps
Hybrid search
Add sparse embeddings for keyword precision
Components
Add reranking for better final-result precision
Pipelines
Learn about advanced pipeline patterns