Elasticsearch vector store
Elasticsearch 8.x with indexed kNN over dense_vector and BM25 full-text search, selected via VECTOR_STORE_PROVIDER=elasticsearch.
Enable it
bash
VECTOR_STORE_PROVIDER=elasticsearch
ELASTICSEARCH_URL=http://localhost:9200
ELASTICSEARCH_API_KEY=your-api-key
# or, instead of the API key:
ELASTICSEARCH_USER=elastic
ELASTICSEARCH_PASSWORD=your-passwordInstall the client: pip install elasticsearch.
Configuration
| Variable | Default | Description |
|---|---|---|
VECTOR_STORE_PROVIDER | pgvector | Set to elasticsearch to use this store. |
ELASTICSEARCH_URL | http://localhost:9200 | URL of the Elasticsearch 8.x cluster. |
ELASTICSEARCH_API_KEY | (none) | Optional API-key auth. |
ELASTICSEARCH_USER | (none) | Optional basic-auth username, paired with the password. |
ELASTICSEARCH_PASSWORD | (none) | Optional basic-auth password, paired with the user. |
Notes
- Unit-tested against a mocked Elasticsearch client, not integration-tested against a live cluster. The kNN/BM25 request bodies are asserted structurally, not executed, so smoke-test before production use.
- Requires Elasticsearch 8.x for the
dense_vectorfield with indexed kNN and cosine similarity. ES 7.x kNN viascript_scoreis not implemented as a fallback. keyword_searchis native BM25 via amatchquery over the analyzedpayload.datafield; scores are unbounded (unlikets_rank's 0..1) and the caller normalizes before fusion.list/searchcap out at ES'smax_result_window(10k by default); deepoffsetpaging past that raises rather than silently truncating.increment_accessusesupdate_by_querywith a painless script: it is not transactional, and a concurrent write can cause a version conflict (retried once, then skipped). Writes userefresh="wait_for"so read-after-write behaves like Postgres, andvalid_touses a far-future sentinel date for'infinity'.