@omendb/omendb 0.0.25 → 0.0.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/index.d.ts +103 -31
  2. package/index.js +62 -49
  3. package/package.json +6 -6
package/index.d.ts CHANGED
@@ -8,21 +8,32 @@ export declare class VectorDatabase {
8
8
  * - Single-vector: items have `vector` field
9
9
  * - Multi-vector: items have `vectors` field (array of vectors)
10
10
  *
11
- * @param items - Array of {id, vector, metadata?} or {id, vectors, metadata?}
12
- * @returns Array of internal indices
11
+ * When any item includes a `text` field, text search is automatically enabled.
12
+ * This allows immediate use of searchHybrid() without calling enableTextSearch().
13
+ *
14
+ * @param items - Array of {id, vector, metadata?, text?} or {id, vectors, metadata?}
15
+ * @returns Number of vectors inserted/updated
13
16
  */
14
- set(items: Array<SetItem>): Array<number>
17
+ set(items: Array<SetItem>): number
15
18
  /**
16
19
  * Search for k nearest neighbors.
17
20
  *
18
21
  * @param query - Query vector (number[] or Float32Array)
19
22
  * @param k - Number of results to return
20
- * @param ef - Optional search width override
21
- * @param filter - Optional metadata filter (e.g., {category: "foo"} or {price: {$gt: 10}})
22
- * @param maxDistance - Optional max distance threshold (filter out distant results)
23
- * @returns Array of {id, distance, metadata}
23
+ * @param options - Optional search options: {filter?, ef?, maxDistance?}
24
+ * @returns Array of {id, distance, score, metadata}
25
+ *
26
+ * @example
27
+ * ```javascript
28
+ * // Basic search
29
+ * db.search([1, 0, 0, 0], 10);
30
+ *
31
+ * // With options
32
+ * db.search([1, 0, 0, 0], 10, { filter: { category: "A" }, ef: 200 });
33
+ * db.search([1, 0, 0, 0], 10, { maxDistance: 0.5 });
34
+ * ```
24
35
  */
25
- search(query: Array<number> | Float32Array, k: number, ef?: number | undefined | null, filter?: Record<string, unknown> | undefined, maxDistance?: number | undefined | null): Array<SearchResult>
36
+ search(query: Array<number> | Float32Array, k: number, options?: { filter?: Record<string, unknown>; ef?: number; maxDistance?: number } | undefined): Array<SearchResult>
26
37
  /**
27
38
  * Search multi-vector store with query tokens.
28
39
  *
@@ -47,9 +58,21 @@ export declare class VectorDatabase {
47
58
  /**
48
59
  * Delete vectors by ID.
49
60
  *
61
+ * Accepts either a single ID string or an array of IDs.
62
+ *
63
+ * @param ids - Single ID string or array of IDs to delete
50
64
  * @returns Number of vectors deleted
65
+ *
66
+ * @example
67
+ * ```javascript
68
+ * // Delete single
69
+ * db.delete("doc1");
70
+ *
71
+ * // Delete multiple
72
+ * db.delete(["doc1", "doc2", "doc3"]);
73
+ * ```
51
74
  */
52
- delete(ids: Array<string>): number
75
+ delete(ids: string | Array<string>): number
53
76
  /**
54
77
  * Delete vectors matching a metadata filter.
55
78
  *
@@ -94,8 +117,28 @@ export declare class VectorDatabase {
94
117
  * ```
95
118
  */
96
119
  count(filter?: Record<string, unknown> | undefined): number
97
- /** Update a vector's data and/or metadata. */
98
- update(id: string, vector: Array<number> | Float32Array, metadata?: Record<string, unknown> | undefined): void
120
+ /**
121
+ * Update a vector's data, metadata, and/or text.
122
+ *
123
+ * @param id - Vector ID to update
124
+ * @param options - Update options: {vector?, metadata?, text?}
125
+ *
126
+ * @example
127
+ * ```javascript
128
+ * // Update vector only
129
+ * db.update("doc1", { vector: [1, 0, 0, 0] });
130
+ *
131
+ * // Update metadata only
132
+ * db.update("doc1", { metadata: { status: "active" } });
133
+ *
134
+ * // Update text (re-indexed for BM25 search)
135
+ * db.update("doc1", { text: "Updated content for search" });
136
+ *
137
+ * // Update multiple fields
138
+ * db.update("doc1", { vector: [...], metadata: {...}, text: "..." });
139
+ * ```
140
+ */
141
+ update(id: string, options: { vector?: number[] | Float32Array; metadata?: Record<string, unknown>; text?: string }): void
99
142
  /** Get number of vectors in database. */
100
143
  get length(): number
101
144
  /** Get vector dimensions of this database. */
@@ -122,20 +165,11 @@ export declare class VectorDatabase {
122
165
  /** Delete a collection. */
123
166
  deleteCollection(name: string): void
124
167
  /**
125
- * Enable text search for hybrid (vector + text) search.
168
+ * Check if text search is enabled.
126
169
  *
127
- * Must be called before using setWithText() or hybridSearch().
170
+ * Text search is automatically enabled when using set() with text field.
128
171
  */
129
- enableTextSearch(): void
130
- /** Check if text search is enabled. */
131
172
  get hasTextSearch(): boolean
132
- /**
133
- * Set vectors with associated text for hybrid search.
134
- *
135
- * @param items - Array of {id, vector, text, metadata?}
136
- * @returns Array of internal indices
137
- */
138
- setWithText(items: Array<VectorItemWithText>): Array<number>
139
173
  /**
140
174
  * Search using text only (BM25 scoring).
141
175
  *
@@ -143,7 +177,7 @@ export declare class VectorDatabase {
143
177
  * @param k - Number of results
144
178
  * @returns Array of {id, score, metadata}
145
179
  */
146
- textSearch(query: string, k: number): Array<TextSearchResult>
180
+ searchText(query: string, k: number): Array<TextSearchResult>
147
181
  /**
148
182
  * Hybrid search combining vector similarity and text relevance.
149
183
  *
@@ -152,13 +186,24 @@ export declare class VectorDatabase {
152
186
  * @param queryVector - Query embedding
153
187
  * @param queryText - Text query for BM25
154
188
  * @param k - Number of results
155
- * @param filter - Optional metadata filter
156
- * @param alpha - Weight for vector vs text (0.0=text only, 1.0=vector only, default=0.5)
157
- * @param rrfK - RRF constant (default=60, higher reduces rank influence)
158
- * @param subscores - Return separate keyword_score and semantic_score (default: false)
159
- * @returns Array of {id, score, metadata, keyword_score?, semantic_score?}
189
+ * @param options - Optional: {filter?, alpha?, rrfK?, subscores?}
190
+ * @returns Array of {id, score, metadata, keywordScore?, semanticScore?}
191
+ *
192
+ * @example
193
+ * ```javascript
194
+ * // Basic hybrid search
195
+ * db.searchHybrid([1, 0, 0, 0], "machine learning", 10);
196
+ *
197
+ * // With options
198
+ * db.searchHybrid([1, 0, 0, 0], "query", 10, {
199
+ * filter: { type: "ml" },
200
+ * alpha: 0.7,
201
+ * rrfK: 60,
202
+ * subscores: true
203
+ * });
204
+ * ```
160
205
  */
161
- hybridSearch(queryVector: Array<number> | Float32Array, queryText: string, k: number, filter?: Record<string, unknown> | undefined, alpha?: number | undefined | null, rrfK?: number | undefined | null, subscores?: boolean | undefined | null): Array<HybridSearchResult>
206
+ searchHybrid(queryVector: Array<number> | Float32Array, queryText: string, k: number, options?: { filter?: Record<string, unknown>; alpha?: number; rrfK?: number; subscores?: boolean } | undefined): Array<HybridSearchResult>
162
207
  /**
163
208
  * Flush pending changes to disk.
164
209
  *
@@ -226,6 +271,31 @@ export declare class VectorDatabase {
226
271
  * @returns true if ID exists and is not deleted
227
272
  */
228
273
  exists(id: string): boolean
274
+ /**
275
+ * Alias for exists() - check if an ID exists in the database.
276
+ *
277
+ * @param id - Vector ID to check
278
+ * @returns true if ID exists and is not deleted
279
+ */
280
+ has(id: string): boolean
281
+ /**
282
+ * Search for the single nearest neighbor.
283
+ *
284
+ * Convenience method that returns the top result or null if no matches.
285
+ *
286
+ * @param query - Query vector (number[] or Float32Array)
287
+ * @param options - Optional search options: {filter?, ef?, maxDistance?}
288
+ * @returns Single result or null
289
+ *
290
+ * @example
291
+ * ```javascript
292
+ * const nearest = db.searchOne([1, 0, 0, 0]);
293
+ * if (nearest) {
294
+ * console.log(`Found: ${nearest.id} at distance ${nearest.distance}`);
295
+ * }
296
+ * ```
297
+ */
298
+ searchOne(query: Array<number> | Float32Array, options?: { filter?: Record<string, unknown>; ef?: number; maxDistance?: number } | undefined): SearchResult | null
229
299
  /**
230
300
  * Get multiple vectors by ID.
231
301
  *
@@ -351,6 +421,8 @@ export interface OpenOptions {
351
421
  export interface SearchResult {
352
422
  id: string
353
423
  distance: number
424
+ /** Normalized similarity score (0-1, higher = more similar) */
425
+ score: number
354
426
  /** Metadata as JSON (using serde-json feature) */
355
427
  metadata: Record<string, unknown>
356
428
  }
@@ -363,8 +435,8 @@ export interface SetItem {
363
435
  vectors?: Float32Array[] | undefined
364
436
  /** Optional metadata */
365
437
  metadata?: Record<string, unknown> | undefined
366
- /** Optional document text (stored in metadata.document) */
367
- document?: string
438
+ /** Optional text for hybrid search (auto-enables text search, stored in metadata.text) */
439
+ text?: string
368
440
  }
369
441
 
370
442
  export interface StatsResult {
package/index.js CHANGED
@@ -161,15 +161,17 @@ class VectorDatabase {
161
161
  * - Single-vector: items have `vector` field
162
162
  * - Multi-vector: items have `vectors` field (array of vectors)
163
163
  *
164
- * @param {Array<{id: string, vector?: Float32Array|number[], vectors?: Float32Array[]|number[][], metadata?: object}>} items
165
- * @returns {number[]} Array of internal indices
164
+ * When any item includes a `text` field, text search is automatically enabled.
165
+ *
166
+ * @param {Array<{id: string, vector?: Float32Array|number[], vectors?: Float32Array[]|number[][], metadata?: object, text?: string}>} items
167
+ * @returns {number} Number of vectors inserted/updated
166
168
  */
167
169
  set(items) {
168
170
  if (!Array.isArray(items)) {
169
171
  throw new Error("set() requires an array of items");
170
172
  }
171
173
  if (items.length === 0) {
172
- return [];
174
+ return 0;
173
175
  }
174
176
  // Unified set() handles both single and multi-vector via native set()
175
177
  return this._native.set(items.map(this._native.isMultiVector ? convertMultiVectorItem : convertVectorItem));
@@ -184,13 +186,8 @@ class VectorDatabase {
184
186
  *
185
187
  * @param {number[]|Float32Array|number[][]|Float32Array[]} query - Query vector(s)
186
188
  * @param {number} k - Number of results to return
187
- * @param {object} [options] - Search options
188
- * @param {number} [options.ef] - Search width override (single-vector only)
189
- * @param {object} [options.filter] - Metadata filter (single-vector only)
190
- * @param {number} [options.maxDistance] - Max distance threshold (single-vector only)
191
- * @param {boolean} [options.rerank] - Enable MaxSim reranking (multi-vector, default: true)
192
- * @param {number} [options.rerankFactor] - Rerank candidate multiplier (multi-vector, default: 4)
193
- * @returns {Array<{id: string, distance: number, metadata: object}>}
189
+ * @param {object} [options] - Search options: {filter?, ef?, maxDistance?}
190
+ * @returns {Array<{id: string, distance: number, score: number, metadata: object}>}
194
191
  */
195
192
  search(query, k, options) {
196
193
  if (this._native.isMultiVector) {
@@ -199,26 +196,22 @@ class VectorDatabase {
199
196
  const rerankFactor = options?.rerankFactor;
200
197
  return this._native.searchMulti(query, k, rerank, rerankFactor);
201
198
  } else {
202
- // Single-vector store - support both old positional args and new options object
203
- if (typeof options === "object" && options !== null && !Array.isArray(options)) {
204
- // New options object style
205
- return this._native.search(
206
- query,
207
- k,
208
- options.ef,
209
- options.filter,
210
- options.maxDistance,
211
- );
212
- } else {
213
- // Legacy positional args: search(query, k, ef, filter, maxDistance)
214
- const ef = options; // 3rd arg was ef in old API
215
- const filter = arguments[3];
216
- const maxDistance = arguments[4];
217
- return this._native.search(query, k, ef, filter, maxDistance);
218
- }
199
+ // Single-vector store - pass options object directly to native
200
+ return this._native.search(query, k, options);
219
201
  }
220
202
  }
221
203
 
204
+ /**
205
+ * Search for the single nearest neighbor.
206
+ *
207
+ * @param {number[]|Float32Array} query - Query vector
208
+ * @param {object} [options] - Search options: {filter?, ef?, maxDistance?}
209
+ * @returns {{id: string, distance: number, score: number, metadata: object}|null}
210
+ */
211
+ searchOne(query, options) {
212
+ return this._native.searchOne(query, options);
213
+ }
214
+
222
215
  searchBatch(queries, k, ef) {
223
216
  return this._native.searchBatch(queries, k, ef);
224
217
  }
@@ -239,8 +232,14 @@ class VectorDatabase {
239
232
  return this._native.count(filter);
240
233
  }
241
234
 
242
- update(id, vector, metadata) {
243
- return this._native.update(id, vector, metadata);
235
+ /**
236
+ * Update a vector's data, metadata, and/or text.
237
+ *
238
+ * @param {string} id - Vector ID to update
239
+ * @param {object} options - Update options: {vector?, metadata?, text?}
240
+ */
241
+ update(id, options) {
242
+ return this._native.update(id, options);
244
243
  }
245
244
 
246
245
  get length() {
@@ -283,32 +282,32 @@ class VectorDatabase {
283
282
  return this._native.deleteCollection(name);
284
283
  }
285
284
 
286
- enableTextSearch() {
287
- return this._native.enableTextSearch();
288
- }
289
-
290
285
  get hasTextSearch() {
291
286
  return this._native.hasTextSearch;
292
287
  }
293
288
 
294
- setWithText(items) {
295
- return this._native.setWithText(items.map(convertVectorItem));
296
- }
297
-
298
- textSearch(query, k) {
299
- return this._native.textSearch(query, k);
289
+ /**
290
+ * Search using text only (BM25 scoring).
291
+ *
292
+ * @param {string} query - Text query
293
+ * @param {number} k - Number of results
294
+ * @returns {Array<{id: string, score: number, metadata: object}>}
295
+ */
296
+ searchText(query, k) {
297
+ return this._native.searchText(query, k);
300
298
  }
301
299
 
302
- hybridSearch(queryVector, queryText, k, filter, alpha, rrfK, subscores) {
303
- return this._native.hybridSearch(
304
- queryVector,
305
- queryText,
306
- k,
307
- filter,
308
- alpha,
309
- rrfK,
310
- subscores,
311
- );
300
+ /**
301
+ * Hybrid search combining vector similarity and text relevance.
302
+ *
303
+ * @param {number[]|Float32Array} queryVector - Query embedding
304
+ * @param {string} queryText - Text query for BM25
305
+ * @param {number} k - Number of results
306
+ * @param {object} [options] - Options: {filter?, alpha?, rrfK?, subscores?}
307
+ * @returns {Array<{id: string, score: number, metadata: object, keywordScore?: number, semanticScore?: number}>}
308
+ */
309
+ searchHybrid(queryVector, queryText, k, options) {
310
+ return this._native.searchHybrid(queryVector, queryText, k, options);
312
311
  }
313
312
 
314
313
  flush() {
@@ -339,9 +338,23 @@ class VectorDatabase {
339
338
  return this._native.exists(id);
340
339
  }
341
340
 
341
+ /**
342
+ * Alias for exists() - check if an ID exists in the database.
343
+ *
344
+ * @param {string} id - Vector ID to check
345
+ * @returns {boolean}
346
+ */
347
+ has(id) {
348
+ return this._native.has(id);
349
+ }
350
+
342
351
  getBatch(ids) {
343
352
  return this._native.getBatch(ids);
344
353
  }
354
+
355
+ compact() {
356
+ return this._native.compact();
357
+ }
345
358
  }
346
359
 
347
360
  function open(path, options) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omendb/omendb",
3
- "version": "0.0.25",
3
+ "version": "0.0.26",
4
4
  "description": "Fast embedded vector database with HNSW + ACORN-1 filtered search",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -50,10 +50,10 @@
50
50
  "omendb.node"
51
51
  ],
52
52
  "optionalDependencies": {
53
- "@omendb/omendb-darwin-x64": "0.0.25",
54
- "@omendb/omendb-darwin-arm64": "0.0.25",
55
- "@omendb/omendb-linux-x64-gnu": "0.0.25",
56
- "@omendb/omendb-linux-arm64-gnu": "0.0.25",
57
- "@omendb/omendb-win32-x64-msvc": "0.0.25"
53
+ "@omendb/omendb-darwin-x64": "0.0.26",
54
+ "@omendb/omendb-darwin-arm64": "0.0.26",
55
+ "@omendb/omendb-linux-x64-gnu": "0.0.26",
56
+ "@omendb/omendb-linux-arm64-gnu": "0.0.26",
57
+ "@omendb/omendb-win32-x64-msvc": "0.0.26"
58
58
  }
59
59
  }