| name | search-nodejs | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| summary | Couchbase Full-Text Search, vector search, hybrid search, and geospatial search for Node.js | ||||||||||||||||||||||||||
| description | Couchbase Full-Text Search, vector search, hybrid search, and geospatial search for Node.js | ||||||||||||||||||||||||||
| compatibility | Node.js SDK 4.x. Requires couchbase>=4.0. | ||||||||||||||||||||||||||
| metadata |
|
Create an FTS index before running text or vector queries. Use the templates as a starting point:
- FTS index: templates/fts-index-basic.json
- Vector index: templates/vector-index.json
See shared/server/search-concepts.md for setup instructions.
const { SearchQuery, SearchOptions } = require('couchbase');
const result = await cluster.searchQuery(
'hotel-fts',
SearchQuery.match('ocean view').field('description'),
new SearchOptions({ limit: 10, fields: ['name', 'city', 'stars'] })
);
for (const row of result.rows)
console.log(row.id, row.score, row.fields);const { VectorSearch, VectorQuery } = require('couchbase');
const queryVector = await embeddingModel.encode(question); // number[]
const result = await cluster.searchQuery(
'product-vector',
VectorSearch.fromVectorQuery(
VectorQuery.create('embedding', queryVector).numCandidates(5)
),
new SearchOptions({ fields: ['name', 'description'] })
);const { VectorSearch, VectorQuery, VectorQueryCombination } = require('couchbase');
const queryVector = await embeddingModel.encode(question); // number[]
const result = await cluster.searchQuery(
'product-vector',
VectorSearch.fromVectorQuery(
VectorQuery.create('embedding', queryVector).numCandidates(10)
).withSearchQuery(SearchQuery.match('comfortable hotel').field('description'))
.vectorQueryCombination(VectorQueryCombination.Or),
new SearchOptions({ fields: ['name', 'description'], limit: 5 })
);const result = await cluster.searchQuery(
'hotel-geo',
SearchQuery.geoDistance(37.7749, -122.4194, '10km').field('geo'),
new SearchOptions({ limit: 20, fields: ['name', 'geo'] })
);const upsertResult = await collection.upsert('hotel::new', { name: 'New Hotel' });
const ms = couchbase.MutationState.from(upsertResult);
const result = await cluster.searchQuery(
'hotel-fts',
SearchQuery.match('New Hotel').field('name'),
new SearchOptions({ consistentWith: ms, limit: 5 })
);// Page 3 (0-indexed skip)
const result = await cluster.searchQuery(
'hotel-fts',
SearchQuery.match('ocean view').field('description'),
new SearchOptions({ limit: 10, skip: 20 })
);SearchQuery.match('ocean view').field('description') // full-text with analysis
SearchQuery.term('airline').field('type') // exact token
SearchQuery.prefix('air').field('name') // prefix / autocomplete
SearchQuery.fuzzy('hotl').fuzziness(1) // typo-tolerant
SearchQuery.numericRange().min(3.0).max(5.0).field('stars') // range
SearchQuery.conjuncts( // AND
SearchQuery.match('hotel').field('type'),
SearchQuery.numericRange().min(4.0).field('stars')
)SELECT name, SEARCH_SCORE() AS score
FROM `travel-sample`.inventory.hotel AS h
WHERE SEARCH(h, {"query": {"match": "ocean view", "field": "description"}}, {"index": "hotel-fts"})
ORDER BY SEARCH_SCORE() DESC LIMIT 10;Shared concepts: shared/server/search-concepts.md — prerequisites, hybrid search, RYOW, pagination, query types.