Elasticsearch
Replace VitNode's default Postgres search provider with Elasticsearch or OpenSearch and rebuild your index safely.
Use Elasticsearch when your site-wide search needs fuzzy matching, custom ranking, or a search cluster separate from Postgres. VitNode keeps Postgres as the canonical index; this adapter mirrors it, so switching is pleasantly boring.
Before you begin
-
An Elasticsearch or OpenSearch cluster. For a local try, start a single-node Elasticsearch in Docker. It has security switched off, so keep it on your machine:
docker run -d --name vitnode-elasticsearch -p 9200:9200 \ -e discovery.type=single-node -e xpack.security.enabled=false \ docker.elastic.co/elasticsearch/elasticsearch:9.1.0curl http://localhost:9200answers with the cluster name and version once it is up. -
An AdminCP account with
system:can_manage_search(root roles have it) to run the first rebuild.
Switch to Elasticsearch
Install the adapter
Run this in the app or API workspace that owns vitnode.api.config.ts.
bun add @vitnode/elasticsearch@canaryAdd the cluster URL and adapter
Set ELASTICSEARCH_NODE to your Elasticsearch or OpenSearch endpoint, then
register the adapter in the API config.
ELASTICSEARCH_NODE=http://localhost:9200import { ElasticsearchSearchAdapter } from '@vitnode/elasticsearch'
export const vitNodeApiConfig = buildApiConfig({
search: {
adapter: ElasticsearchSearchAdapter({
node: process.env.ELASTICSEARCH_NODE,
index: 'vitnode',
}),
},
plugins: [blogApiPlugin()],
})For Elastic Cloud, use cloudId and apiKey instead of node. The adapter
also accepts username and password for a self-hosted secured cluster.
Rebuild the mirror
Restart the API, then open Debug Panel ā Search in the AdminCP
(/admin/core/debug/search) and run Rebuild index. New changes are mirrored automatically; the rebuild fills
the historical records already in Postgres. Rebuilding (and clearing a
collection) needs the Rebuild and clear the search index permission
(system:can_manage_search) - viewing the section alone is not enough.
Elasticsearch counts matches up to 10,000, the same depth you can page to.
Past that, totalCount reads 10,000 and means "at least this many" - nobody
scrolls that far anyway.
Do not delete core_search_index. It remains VitNode's source of truth and
lets you switch providers without losing your map back home.
Check the result
-
Debug Panel ā Search names
elasticsearchon the Engine card, and the collection counts match what you indexed. -
A search from the public API returns hits from the cluster:
curl "http://localhost:3000/api/@vitnode/core/search?search=hello"
Upgrading an index from an earlier version
Documents now carry authorIds (a list) instead of authorId, plus drafts as
private documents. If your index was created before that, delete it in
Elasticsearch and run Rebuild index. VitNode recreates it with the new
mapping.
Documents now carry an itemKey keyword with the record id as text, so search
can find uuid and bigint records. VitNode
adds the field to an existing index the first time it uses it. Older documents
get a value on the next Rebuild index; until then, results fall back to
the numeric itemId, which works for serial ids only.