@omendb/omendb 0.0.25 → 0.0.27
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.
- package/README.md +13 -10
- package/index.d.ts +144 -137
- package/index.js +53 -58
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ Fast embedded vector database with HNSW indexing for Node.js and Bun.
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
npm install omendb
|
|
8
|
+
npm install @omendb/omendb
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
## Quick Start
|
|
@@ -191,28 +191,31 @@ db.setWithText([
|
|
|
191
191
|
]);
|
|
192
192
|
```
|
|
193
193
|
|
|
194
|
-
#### `db.
|
|
194
|
+
#### `db.searchText(query, k)`
|
|
195
195
|
|
|
196
196
|
BM25 text-only search.
|
|
197
197
|
|
|
198
198
|
```typescript
|
|
199
|
-
const results = db.
|
|
199
|
+
const results = db.searchText("machine learning", 10);
|
|
200
200
|
// [{ id, score, metadata }, ...]
|
|
201
201
|
```
|
|
202
202
|
|
|
203
|
-
#### `db.
|
|
203
|
+
#### `db.searchHybrid(queryVector, queryText, k, options?)`
|
|
204
204
|
|
|
205
|
-
Combined vector + text search.
|
|
205
|
+
Combined vector + text search using Reciprocal Rank Fusion.
|
|
206
206
|
|
|
207
207
|
```typescript
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
208
|
+
// Basic
|
|
209
|
+
const results = db.searchHybrid(queryVector, "machine learning", 10);
|
|
210
|
+
|
|
211
|
+
// With options
|
|
212
|
+
const results = db.searchHybrid(queryVector, "machine learning", 10, {
|
|
212
213
|
alpha: 0.7, // 0=text only, 1=vector only (default: 0.5)
|
|
214
|
+
rrfK: 60, // RRF constant (default: 60)
|
|
215
|
+
filter: { category: "ml" },
|
|
213
216
|
subscores: true, // Include separate scores
|
|
214
217
|
});
|
|
215
|
-
// [{ id, score, metadata,
|
|
218
|
+
// [{ id, score, metadata, keywordScore?, semanticScore? }, ...]
|
|
216
219
|
```
|
|
217
220
|
|
|
218
221
|
### Collections
|
package/index.d.ts
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
/* auto-generated by NAPI-RS */
|
|
2
2
|
/* eslint-disable */
|
|
3
3
|
export declare class VectorDatabase {
|
|
4
|
+
/**
|
|
5
|
+
* Get or create a named collection.
|
|
6
|
+
*
|
|
7
|
+
* Collection handles share state - changes made through one handle
|
|
8
|
+
* are immediately visible through another (no flush required).
|
|
9
|
+
*/
|
|
10
|
+
collection(name: string, embeddingFn?: ((texts: string[]) => Float32Array[]) | undefined): VectorDatabase
|
|
11
|
+
/** List all collections. */
|
|
12
|
+
collections(): Array<string>
|
|
13
|
+
/** Delete a collection. */
|
|
14
|
+
deleteCollection(name: string): void
|
|
4
15
|
/**
|
|
5
16
|
* Insert or update vectors.
|
|
6
17
|
*
|
|
@@ -8,48 +19,33 @@ export declare class VectorDatabase {
|
|
|
8
19
|
* - Single-vector: items have `vector` field
|
|
9
20
|
* - Multi-vector: items have `vectors` field (array of vectors)
|
|
10
21
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*/
|
|
14
|
-
set(items: Array<SetItem>): Array<number>
|
|
15
|
-
/**
|
|
16
|
-
* Search for k nearest neighbors.
|
|
17
|
-
*
|
|
18
|
-
* @param query - Query vector (number[] or Float32Array)
|
|
19
|
-
* @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}
|
|
24
|
-
*/
|
|
25
|
-
search(query: Array<number> | Float32Array, k: number, ef?: number | undefined | null, filter?: Record<string, unknown> | undefined, maxDistance?: number | undefined | null): Array<SearchResult>
|
|
26
|
-
/**
|
|
27
|
-
* Search multi-vector store with query tokens.
|
|
28
|
-
*
|
|
29
|
-
* Internal method used by unified search() for multi-vector stores.
|
|
30
|
-
*
|
|
31
|
-
* @param query - Query tokens (number[][] or Float32Array[])
|
|
32
|
-
* @param k - Number of results to return
|
|
33
|
-
* @param rerank - Enable MaxSim reranking for better quality (default: true)
|
|
34
|
-
* @param rerankFactor - Fetch k*rerankFactor candidates before reranking (default: 32)
|
|
35
|
-
* @returns Array of {id, distance, metadata}
|
|
36
|
-
*/
|
|
37
|
-
searchMulti(query: Array<Array<number>> | Array<Float32Array>, k: number, rerank?: boolean | undefined | null, rerankFactor?: number | undefined | null): Array<SearchResult>
|
|
38
|
-
/**
|
|
39
|
-
* Batch search with parallel execution (async).
|
|
22
|
+
* When any item includes a `text` field, text search is automatically enabled.
|
|
23
|
+
* This allows immediate use of searchHybrid() without calling enableTextSearch().
|
|
40
24
|
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
25
|
+
* @param items - Array of {id, vector, metadata?, text?} or {id, vectors, metadata?}
|
|
26
|
+
* @returns Number of vectors inserted/updated
|
|
43
27
|
*/
|
|
44
|
-
|
|
28
|
+
set(items: Array<SetItem>): Promise<number>
|
|
45
29
|
/** Get a vector by ID. */
|
|
46
30
|
get(id: string): GetResult | null
|
|
47
31
|
/**
|
|
48
32
|
* Delete vectors by ID.
|
|
49
33
|
*
|
|
34
|
+
* Accepts either a single ID string or an array of IDs.
|
|
35
|
+
*
|
|
36
|
+
* @param ids - Single ID string or array of IDs to delete
|
|
50
37
|
* @returns Number of vectors deleted
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```javascript
|
|
41
|
+
* // Delete single
|
|
42
|
+
* db.delete("doc1");
|
|
43
|
+
*
|
|
44
|
+
* // Delete multiple
|
|
45
|
+
* db.delete(["doc1", "doc2", "doc3"]);
|
|
46
|
+
* ```
|
|
51
47
|
*/
|
|
52
|
-
delete(ids: Array<string>): number
|
|
48
|
+
delete(ids: string | Array<string>): number
|
|
53
49
|
/**
|
|
54
50
|
* Delete vectors matching a metadata filter.
|
|
55
51
|
*
|
|
@@ -94,14 +90,36 @@ export declare class VectorDatabase {
|
|
|
94
90
|
* ```
|
|
95
91
|
*/
|
|
96
92
|
count(filter?: Record<string, unknown> | undefined): number
|
|
97
|
-
/**
|
|
98
|
-
|
|
93
|
+
/**
|
|
94
|
+
* Update a vector's data, metadata, and/or text.
|
|
95
|
+
*
|
|
96
|
+
* @param id - Vector ID to update
|
|
97
|
+
* @param options - Update options: {vector?, metadata?, text?}
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```javascript
|
|
101
|
+
* // Update vector only
|
|
102
|
+
* db.update("doc1", { vector: [1, 0, 0, 0] });
|
|
103
|
+
*
|
|
104
|
+
* // Update metadata only
|
|
105
|
+
* db.update("doc1", { metadata: { status: "active" } });
|
|
106
|
+
*
|
|
107
|
+
* // Update text (re-indexed for BM25 search)
|
|
108
|
+
* db.update("doc1", { text: "Updated content for search" });
|
|
109
|
+
*
|
|
110
|
+
* // Update multiple fields
|
|
111
|
+
* db.update("doc1", { vector: [...], metadata: {...}, text: "..." });
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
update(id: string, options: { vector?: number[] | Float32Array; metadata?: Record<string, unknown>; text?: string }): void
|
|
99
115
|
/** Get number of vectors in database. */
|
|
100
116
|
get length(): number
|
|
101
117
|
/** Get vector dimensions of this database. */
|
|
102
118
|
get dimensions(): number
|
|
103
119
|
/** Check if this is a multi-vector store. */
|
|
104
120
|
get isMultiVector(): boolean
|
|
121
|
+
/** Check if an embedding function is configured. */
|
|
122
|
+
get hasEmbeddingFn(): boolean
|
|
105
123
|
/** Check if database is empty. */
|
|
106
124
|
isEmpty(): boolean
|
|
107
125
|
/** Get database statistics. */
|
|
@@ -110,61 +128,6 @@ export declare class VectorDatabase {
|
|
|
110
128
|
get efSearch(): number
|
|
111
129
|
/** Set ef_search value. */
|
|
112
130
|
set efSearch(efSearch: number)
|
|
113
|
-
/**
|
|
114
|
-
* Get or create a named collection.
|
|
115
|
-
*
|
|
116
|
-
* Collection handles share state - changes made through one handle
|
|
117
|
-
* are immediately visible through another (no flush required).
|
|
118
|
-
*/
|
|
119
|
-
collection(name: string): VectorDatabase
|
|
120
|
-
/** List all collections. */
|
|
121
|
-
collections(): Array<string>
|
|
122
|
-
/** Delete a collection. */
|
|
123
|
-
deleteCollection(name: string): void
|
|
124
|
-
/**
|
|
125
|
-
* Enable text search for hybrid (vector + text) search.
|
|
126
|
-
*
|
|
127
|
-
* Must be called before using setWithText() or hybridSearch().
|
|
128
|
-
*/
|
|
129
|
-
enableTextSearch(): void
|
|
130
|
-
/** Check if text search is enabled. */
|
|
131
|
-
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
|
-
/**
|
|
140
|
-
* Search using text only (BM25 scoring).
|
|
141
|
-
*
|
|
142
|
-
* @param query - Text query
|
|
143
|
-
* @param k - Number of results
|
|
144
|
-
* @returns Array of {id, score, metadata}
|
|
145
|
-
*/
|
|
146
|
-
textSearch(query: string, k: number): Array<TextSearchResult>
|
|
147
|
-
/**
|
|
148
|
-
* Hybrid search combining vector similarity and text relevance.
|
|
149
|
-
*
|
|
150
|
-
* Uses Reciprocal Rank Fusion (RRF) to combine HNSW and BM25 results.
|
|
151
|
-
*
|
|
152
|
-
* @param queryVector - Query embedding
|
|
153
|
-
* @param queryText - Text query for BM25
|
|
154
|
-
* @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?}
|
|
160
|
-
*/
|
|
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>
|
|
162
|
-
/**
|
|
163
|
-
* Flush pending changes to disk.
|
|
164
|
-
*
|
|
165
|
-
* For hybrid search, this commits text index changes.
|
|
166
|
-
*/
|
|
167
|
-
flush(): void
|
|
168
131
|
/**
|
|
169
132
|
* Compact the database by removing deleted records and reclaiming space.
|
|
170
133
|
*
|
|
@@ -235,6 +198,90 @@ export declare class VectorDatabase {
|
|
|
235
198
|
* @returns Array of results in same order as input, null for missing IDs
|
|
236
199
|
*/
|
|
237
200
|
getBatch(ids: Array<string>): Array<GetResult | undefined | null>
|
|
201
|
+
/**
|
|
202
|
+
* Check if text search is enabled.
|
|
203
|
+
*
|
|
204
|
+
* Text search is automatically enabled when using set() with text field.
|
|
205
|
+
*/
|
|
206
|
+
get hasTextSearch(): boolean
|
|
207
|
+
/**
|
|
208
|
+
* Search using text only (BM25 scoring).
|
|
209
|
+
*
|
|
210
|
+
* @param query - Text query
|
|
211
|
+
* @param k - Number of results
|
|
212
|
+
* @returns Array of {id, score, metadata}
|
|
213
|
+
*/
|
|
214
|
+
searchText(query: string, k: number): Array<TextSearchResult>
|
|
215
|
+
/**
|
|
216
|
+
* Hybrid search combining vector similarity and text relevance.
|
|
217
|
+
*
|
|
218
|
+
* Uses Reciprocal Rank Fusion (RRF) to combine HNSW and BM25 results.
|
|
219
|
+
*
|
|
220
|
+
* @param queryVector - Query embedding
|
|
221
|
+
* @param queryText - Text query for BM25
|
|
222
|
+
* @param k - Number of results
|
|
223
|
+
* @param options - Optional: {filter?, alpha?, rrfK?, subscores?}
|
|
224
|
+
* @returns Array of {id, score, metadata, keywordScore?, semanticScore?}
|
|
225
|
+
*
|
|
226
|
+
* @example
|
|
227
|
+
* ```javascript
|
|
228
|
+
* // Basic hybrid search
|
|
229
|
+
* db.searchHybrid([1, 0, 0, 0], "machine learning", 10);
|
|
230
|
+
*
|
|
231
|
+
* // With options
|
|
232
|
+
* db.searchHybrid([1, 0, 0, 0], "query", 10, {
|
|
233
|
+
* filter: { type: "ml" },
|
|
234
|
+
* alpha: 0.7,
|
|
235
|
+
* rrfK: 60,
|
|
236
|
+
* subscores: true
|
|
237
|
+
* });
|
|
238
|
+
* ```
|
|
239
|
+
*/
|
|
240
|
+
searchHybrid(queryVector: Array<number> | Float32Array | string, queryText: string | undefined | null, k: number, options?: { filter?: Record<string, unknown>; alpha?: number; rrfK?: number; subscores?: boolean } | undefined): Promise<Array<HybridSearchResult>>
|
|
241
|
+
/**
|
|
242
|
+
* Flush pending changes to disk.
|
|
243
|
+
*
|
|
244
|
+
* For hybrid search, this commits text index changes.
|
|
245
|
+
*/
|
|
246
|
+
flush(): void
|
|
247
|
+
/**
|
|
248
|
+
* Search for k nearest neighbors.
|
|
249
|
+
*
|
|
250
|
+
* @param query - Query vector (number[] or Float32Array)
|
|
251
|
+
* @param k - Number of results to return
|
|
252
|
+
* @param options - Optional search options: {filter?, ef?, maxDistance?}
|
|
253
|
+
* @returns Array of {id, distance, score, metadata}
|
|
254
|
+
*
|
|
255
|
+
* @example
|
|
256
|
+
* ```javascript
|
|
257
|
+
* // Basic search
|
|
258
|
+
* db.search([1, 0, 0, 0], 10);
|
|
259
|
+
*
|
|
260
|
+
* // With options
|
|
261
|
+
* db.search([1, 0, 0, 0], 10, { filter: { category: "A" }, ef: 200 });
|
|
262
|
+
* db.search([1, 0, 0, 0], 10, { maxDistance: 0.5 });
|
|
263
|
+
* ```
|
|
264
|
+
*/
|
|
265
|
+
search(query: Array<number> | Float32Array | string, k: number, options?: { filter?: Record<string, unknown>; ef?: number; maxDistance?: number } | undefined): Promise<Array<SearchResult>>
|
|
266
|
+
/**
|
|
267
|
+
* Search multi-vector store with query tokens.
|
|
268
|
+
*
|
|
269
|
+
* Internal method used by unified search() for multi-vector stores.
|
|
270
|
+
*
|
|
271
|
+
* @param query - Query tokens (number[][] or Float32Array[])
|
|
272
|
+
* @param k - Number of results to return
|
|
273
|
+
* @param rerank - Enable MaxSim reranking for better quality (default: true)
|
|
274
|
+
* @param rerankFactor - Fetch k*rerankFactor candidates before reranking (default: 32)
|
|
275
|
+
* @returns Array of {id, distance, metadata}
|
|
276
|
+
*/
|
|
277
|
+
searchMulti(query: Array<Array<number>> | Array<Float32Array>, k: number, rerank?: boolean | undefined | null, rerankFactor?: number | undefined | null): Array<SearchResult>
|
|
278
|
+
/**
|
|
279
|
+
* Batch search with parallel execution (async).
|
|
280
|
+
*
|
|
281
|
+
* Runs searches in parallel using rayon on a blocking thread pool,
|
|
282
|
+
* keeping the Node.js event loop free.
|
|
283
|
+
*/
|
|
284
|
+
searchBatch(queries: Array<Array<number> | Float32Array>, k: number, ef?: number | undefined | null): Promise<Array<Array<SearchResult>>>
|
|
238
285
|
}
|
|
239
286
|
|
|
240
287
|
export interface GetResult {
|
|
@@ -253,14 +300,6 @@ export interface HybridSearchResult {
|
|
|
253
300
|
semanticScore?: number
|
|
254
301
|
}
|
|
255
302
|
|
|
256
|
-
export interface MultiVectorItem {
|
|
257
|
-
id: string
|
|
258
|
-
/** Multi-vector data as array of Float32Arrays */
|
|
259
|
-
vectors: Float32Array[]
|
|
260
|
-
/** Optional metadata */
|
|
261
|
-
metadata?: Record<string, unknown> | undefined
|
|
262
|
-
}
|
|
263
|
-
|
|
264
303
|
/**
|
|
265
304
|
* Open or create a vector database.
|
|
266
305
|
*
|
|
@@ -287,16 +326,9 @@ export interface MultiVectorItem {
|
|
|
287
326
|
* quantization: true // or "sq8"
|
|
288
327
|
* });
|
|
289
328
|
*
|
|
290
|
-
* // Quantization with custom rescore settings
|
|
291
|
-
* const db = omendb.open("./mydb", {
|
|
292
|
-
* dimensions: 128,
|
|
293
|
-
* quantization: true,
|
|
294
|
-
* rescore: false, // Disable rescore for max speed
|
|
295
|
-
* oversample: 5.0 // Or increase oversample for better recall
|
|
296
|
-
* });
|
|
297
329
|
* ```
|
|
298
330
|
*/
|
|
299
|
-
export declare function open(path: string, options?: OpenOptions | undefined | null): VectorDatabase
|
|
331
|
+
export declare function open(path: string, options?: OpenOptions | undefined | null, embeddingFn?: ((texts: string[]) => Float32Array[]) | undefined): VectorDatabase
|
|
300
332
|
|
|
301
333
|
/**
|
|
302
334
|
* Configuration options for opening a vector database.
|
|
@@ -306,9 +338,7 @@ export declare function open(path: string, options?: OpenOptions | undefined | n
|
|
|
306
338
|
* - m: 16 (HNSW neighbors per node, higher = better recall, more memory)
|
|
307
339
|
* - efConstruction: 100 (build quality, higher = better graph, slower build)
|
|
308
340
|
* - efSearch: 100 (search quality, higher = better recall, slower search)
|
|
309
|
-
* - quantization: null (true/"sq8" for 4x compression
|
|
310
|
-
* - rescore: true when quantization enabled (rerank candidates with exact distance)
|
|
311
|
-
* - oversample: 3.0 (fetch k*oversample candidates when rescoring)
|
|
341
|
+
* - quantization: null (true/"sq8" for 4x compression)
|
|
312
342
|
* - metric: "l2" (distance metric: "l2", "euclidean", "cosine", "dot", "ip")
|
|
313
343
|
*/
|
|
314
344
|
export interface OpenOptions {
|
|
@@ -326,16 +356,6 @@ export interface OpenOptions {
|
|
|
326
356
|
* - false/null: Full precision (no quantization)
|
|
327
357
|
*/
|
|
328
358
|
quantization?: boolean | string | number | null | undefined
|
|
329
|
-
/**
|
|
330
|
-
* Rescore candidates with exact distance (default: true when quantization enabled)
|
|
331
|
-
* Set to false for maximum speed at the cost of ~20% recall
|
|
332
|
-
*/
|
|
333
|
-
rescore?: boolean
|
|
334
|
-
/**
|
|
335
|
-
* Oversampling factor for rescoring (default: 3.0)
|
|
336
|
-
* Fetches k*oversample candidates then reranks to return top k
|
|
337
|
-
*/
|
|
338
|
-
oversample?: number
|
|
339
359
|
/** Distance metric: "l2"/"euclidean" (default), "cosine", "dot"/"ip" */
|
|
340
360
|
metric?: string
|
|
341
361
|
/**
|
|
@@ -351,6 +371,8 @@ export interface OpenOptions {
|
|
|
351
371
|
export interface SearchResult {
|
|
352
372
|
id: string
|
|
353
373
|
distance: number
|
|
374
|
+
/** Normalized similarity score (0-1, higher = more similar) */
|
|
375
|
+
score: number
|
|
354
376
|
/** Metadata as JSON (using serde-json feature) */
|
|
355
377
|
metadata: Record<string, unknown>
|
|
356
378
|
}
|
|
@@ -363,7 +385,9 @@ export interface SetItem {
|
|
|
363
385
|
vectors?: Float32Array[] | undefined
|
|
364
386
|
/** Optional metadata */
|
|
365
387
|
metadata?: Record<string, unknown> | undefined
|
|
366
|
-
/** Optional
|
|
388
|
+
/** Optional text for hybrid search (auto-enables text search, stored in metadata.text) */
|
|
389
|
+
text?: string
|
|
390
|
+
/** Optional document for auto-embedding via embeddingFn */
|
|
367
391
|
document?: string
|
|
368
392
|
}
|
|
369
393
|
|
|
@@ -378,20 +402,3 @@ export interface TextSearchResult {
|
|
|
378
402
|
score: number
|
|
379
403
|
metadata: Record<string, unknown>
|
|
380
404
|
}
|
|
381
|
-
|
|
382
|
-
export interface VectorItem {
|
|
383
|
-
id: string
|
|
384
|
-
/** Vector data as Float32Array */
|
|
385
|
-
vector: Float32Array
|
|
386
|
-
/** Optional metadata */
|
|
387
|
-
metadata?: Record<string, unknown> | undefined
|
|
388
|
-
/** Optional document text (stored in metadata.document) */
|
|
389
|
-
document?: string
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
export interface VectorItemWithText {
|
|
393
|
-
id: string
|
|
394
|
-
vector: Float32Array
|
|
395
|
-
text: string
|
|
396
|
-
metadata?: Record<string, unknown> | undefined
|
|
397
|
-
}
|
package/index.js
CHANGED
|
@@ -111,6 +111,10 @@ function toFloat32Array(arr) {
|
|
|
111
111
|
|
|
112
112
|
// Convert VectorItem to use Float32Array
|
|
113
113
|
function convertVectorItem(item) {
|
|
114
|
+
// Items with document field are handled by native embedding
|
|
115
|
+
if (item.document !== undefined && item.document !== null) {
|
|
116
|
+
return item;
|
|
117
|
+
}
|
|
114
118
|
if (item.vector === undefined || item.vector === null) {
|
|
115
119
|
if (Array.isArray(item.vectors)) {
|
|
116
120
|
throw new Error(
|
|
@@ -141,11 +145,6 @@ function convertMultiVectorItem(item) {
|
|
|
141
145
|
};
|
|
142
146
|
}
|
|
143
147
|
|
|
144
|
-
// Check if items contain multi-vector data (vectors field must be an array)
|
|
145
|
-
function isMultiVectorItem(item) {
|
|
146
|
-
return Array.isArray(item.vectors);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
148
|
// Wrap VectorDatabase to handle array conversion
|
|
150
149
|
const NativeVectorDatabase = nativeBinding.VectorDatabase;
|
|
151
150
|
|
|
@@ -161,15 +160,17 @@ class VectorDatabase {
|
|
|
161
160
|
* - Single-vector: items have `vector` field
|
|
162
161
|
* - Multi-vector: items have `vectors` field (array of vectors)
|
|
163
162
|
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
163
|
+
* When any item includes a `text` field, text search is automatically enabled.
|
|
164
|
+
*
|
|
165
|
+
* @param {Array<{id: string, vector?: Float32Array|number[], vectors?: Float32Array[]|number[][], metadata?: object, text?: string}>} items
|
|
166
|
+
* @returns {number} Number of vectors inserted/updated
|
|
166
167
|
*/
|
|
167
168
|
set(items) {
|
|
168
169
|
if (!Array.isArray(items)) {
|
|
169
170
|
throw new Error("set() requires an array of items");
|
|
170
171
|
}
|
|
171
172
|
if (items.length === 0) {
|
|
172
|
-
return
|
|
173
|
+
return 0;
|
|
173
174
|
}
|
|
174
175
|
// Unified set() handles both single and multi-vector via native set()
|
|
175
176
|
return this._native.set(items.map(this._native.isMultiVector ? convertMultiVectorItem : convertVectorItem));
|
|
@@ -184,13 +185,8 @@ class VectorDatabase {
|
|
|
184
185
|
*
|
|
185
186
|
* @param {number[]|Float32Array|number[][]|Float32Array[]} query - Query vector(s)
|
|
186
187
|
* @param {number} k - Number of results to return
|
|
187
|
-
* @param {object} [options] - Search options
|
|
188
|
-
* @
|
|
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}>}
|
|
188
|
+
* @param {object} [options] - Search options: {filter?, ef?, maxDistance?}
|
|
189
|
+
* @returns {Array<{id: string, distance: number, score: number, metadata: object}>}
|
|
194
190
|
*/
|
|
195
191
|
search(query, k, options) {
|
|
196
192
|
if (this._native.isMultiVector) {
|
|
@@ -199,23 +195,8 @@ class VectorDatabase {
|
|
|
199
195
|
const rerankFactor = options?.rerankFactor;
|
|
200
196
|
return this._native.searchMulti(query, k, rerank, rerankFactor);
|
|
201
197
|
} else {
|
|
202
|
-
// Single-vector store -
|
|
203
|
-
|
|
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
|
-
}
|
|
198
|
+
// Single-vector store - pass options object directly to native
|
|
199
|
+
return this._native.search(query, k, options);
|
|
219
200
|
}
|
|
220
201
|
}
|
|
221
202
|
|
|
@@ -239,8 +220,14 @@ class VectorDatabase {
|
|
|
239
220
|
return this._native.count(filter);
|
|
240
221
|
}
|
|
241
222
|
|
|
242
|
-
|
|
243
|
-
|
|
223
|
+
/**
|
|
224
|
+
* Update a vector's data, metadata, and/or text.
|
|
225
|
+
*
|
|
226
|
+
* @param {string} id - Vector ID to update
|
|
227
|
+
* @param {object} options - Update options: {vector?, metadata?, text?}
|
|
228
|
+
*/
|
|
229
|
+
update(id, options) {
|
|
230
|
+
return this._native.update(id, options);
|
|
244
231
|
}
|
|
245
232
|
|
|
246
233
|
get length() {
|
|
@@ -255,6 +242,10 @@ class VectorDatabase {
|
|
|
255
242
|
return this._native.isMultiVector;
|
|
256
243
|
}
|
|
257
244
|
|
|
245
|
+
get hasEmbeddingFn() {
|
|
246
|
+
return this._native.hasEmbeddingFn;
|
|
247
|
+
}
|
|
248
|
+
|
|
258
249
|
isEmpty() {
|
|
259
250
|
return this._native.isEmpty();
|
|
260
251
|
}
|
|
@@ -271,8 +262,8 @@ class VectorDatabase {
|
|
|
271
262
|
this._native.efSearch = value;
|
|
272
263
|
}
|
|
273
264
|
|
|
274
|
-
collection(name) {
|
|
275
|
-
return new VectorDatabase(this._native.collection(name));
|
|
265
|
+
collection(name, embeddingFn) {
|
|
266
|
+
return new VectorDatabase(this._native.collection(name, embeddingFn));
|
|
276
267
|
}
|
|
277
268
|
|
|
278
269
|
collections() {
|
|
@@ -283,32 +274,32 @@ class VectorDatabase {
|
|
|
283
274
|
return this._native.deleteCollection(name);
|
|
284
275
|
}
|
|
285
276
|
|
|
286
|
-
enableTextSearch() {
|
|
287
|
-
return this._native.enableTextSearch();
|
|
288
|
-
}
|
|
289
|
-
|
|
290
277
|
get hasTextSearch() {
|
|
291
278
|
return this._native.hasTextSearch;
|
|
292
279
|
}
|
|
293
280
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
281
|
+
/**
|
|
282
|
+
* Search using text only (BM25 scoring).
|
|
283
|
+
*
|
|
284
|
+
* @param {string} query - Text query
|
|
285
|
+
* @param {number} k - Number of results
|
|
286
|
+
* @returns {Array<{id: string, score: number, metadata: object}>}
|
|
287
|
+
*/
|
|
288
|
+
searchText(query, k) {
|
|
289
|
+
return this._native.searchText(query, k);
|
|
300
290
|
}
|
|
301
291
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
292
|
+
/**
|
|
293
|
+
* Hybrid search combining vector similarity and text relevance.
|
|
294
|
+
*
|
|
295
|
+
* @param {number[]|Float32Array} queryVector - Query embedding
|
|
296
|
+
* @param {string} queryText - Text query for BM25
|
|
297
|
+
* @param {number} k - Number of results
|
|
298
|
+
* @param {object} [options] - Options: {filter?, alpha?, rrfK?, subscores?}
|
|
299
|
+
* @returns {Array<{id: string, score: number, metadata: object, keywordScore?: number, semanticScore?: number}>}
|
|
300
|
+
*/
|
|
301
|
+
searchHybrid(queryVector, queryText, k, options) {
|
|
302
|
+
return this._native.searchHybrid(queryVector, queryText, k, options);
|
|
312
303
|
}
|
|
313
304
|
|
|
314
305
|
flush() {
|
|
@@ -342,10 +333,14 @@ class VectorDatabase {
|
|
|
342
333
|
getBatch(ids) {
|
|
343
334
|
return this._native.getBatch(ids);
|
|
344
335
|
}
|
|
336
|
+
|
|
337
|
+
compact() {
|
|
338
|
+
return this._native.compact();
|
|
339
|
+
}
|
|
345
340
|
}
|
|
346
341
|
|
|
347
|
-
function open(path, options) {
|
|
348
|
-
return new VectorDatabase(nativeBinding.open(path, options));
|
|
342
|
+
function open(path, options, embeddingFn) {
|
|
343
|
+
return new VectorDatabase(nativeBinding.open(path, options, embeddingFn));
|
|
349
344
|
}
|
|
350
345
|
|
|
351
346
|
module.exports.VectorDatabase = VectorDatabase;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@omendb/omendb",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.27",
|
|
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.
|
|
54
|
-
"@omendb/omendb-darwin-arm64": "0.0.
|
|
55
|
-
"@omendb/omendb-linux-x64-gnu": "0.0.
|
|
56
|
-
"@omendb/omendb-linux-arm64-gnu": "0.0.
|
|
57
|
-
"@omendb/omendb-win32-x64-msvc": "0.0.
|
|
53
|
+
"@omendb/omendb-darwin-x64": "0.0.27",
|
|
54
|
+
"@omendb/omendb-darwin-arm64": "0.0.27",
|
|
55
|
+
"@omendb/omendb-linux-x64-gnu": "0.0.27",
|
|
56
|
+
"@omendb/omendb-linux-arm64-gnu": "0.0.27",
|
|
57
|
+
"@omendb/omendb-win32-x64-msvc": "0.0.27"
|
|
58
58
|
}
|
|
59
59
|
}
|