@lancedb/lancedb 0.5.2 → 0.7.1
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/Cargo.toml +3 -3
- package/biome.json +19 -3
- package/dist/arrow.d.ts +41 -8
- package/dist/arrow.js +4 -4
- package/dist/connection.d.ts +49 -29
- package/dist/connection.js +21 -73
- package/dist/embedding/embedding_function.d.ts +9 -1
- package/dist/embedding/embedding_function.js +6 -0
- package/dist/embedding/openai.d.ts +6 -5
- package/dist/embedding/openai.js +4 -2
- package/dist/embedding/registry.d.ts +6 -11
- package/dist/index.d.ts +51 -3
- package/dist/index.js +28 -4
- package/dist/merge.d.ts +54 -0
- package/dist/merge.js +64 -0
- package/dist/native.d.ts +29 -3
- package/dist/native.js +26 -9
- package/dist/query.d.ts +33 -10
- package/dist/query.js +100 -13
- package/dist/remote/client.d.ts +28 -0
- package/dist/remote/client.js +172 -0
- package/dist/remote/connection.d.ts +25 -0
- package/dist/remote/connection.js +110 -0
- package/dist/remote/index.d.ts +3 -0
- package/dist/remote/index.js +9 -0
- package/dist/remote/table.d.ts +42 -0
- package/dist/remote/table.js +179 -0
- package/dist/sanitize.d.ts +3 -2
- package/dist/sanitize.js +55 -1
- package/dist/table.d.ts +105 -30
- package/dist/table.js +94 -237
- package/dist/util.d.ts +14 -0
- package/dist/util.js +65 -0
- package/examples/ann_indexes.ts +49 -0
- package/examples/basic.ts +149 -0
- package/examples/embedding.ts +83 -0
- package/examples/filtering.ts +34 -0
- package/examples/jsconfig.json +27 -0
- package/examples/package-lock.json +79 -0
- package/examples/package.json +18 -0
- package/examples/search.ts +37 -0
- package/lancedb/arrow.ts +80 -23
- package/lancedb/connection.ts +107 -92
- package/lancedb/embedding/embedding_function.ts +12 -1
- package/lancedb/embedding/openai.ts +11 -6
- package/lancedb/embedding/registry.ts +34 -22
- package/lancedb/index.ts +101 -2
- package/lancedb/merge.ts +70 -0
- package/lancedb/query.ts +114 -28
- package/lancedb/remote/client.ts +221 -0
- package/lancedb/remote/connection.ts +201 -0
- package/lancedb/remote/index.ts +3 -0
- package/lancedb/remote/table.ts +226 -0
- package/lancedb/sanitize.ts +73 -1
- package/lancedb/table.ts +320 -132
- package/lancedb/util.ts +69 -0
- package/native.d.ts +208 -0
- package/nodejs-artifacts/arrow.d.ts +41 -8
- package/nodejs-artifacts/arrow.js +4 -4
- package/nodejs-artifacts/connection.d.ts +49 -29
- package/nodejs-artifacts/connection.js +21 -73
- package/nodejs-artifacts/embedding/embedding_function.d.ts +9 -1
- package/nodejs-artifacts/embedding/embedding_function.js +6 -0
- package/nodejs-artifacts/embedding/openai.d.ts +6 -5
- package/nodejs-artifacts/embedding/openai.js +4 -2
- package/nodejs-artifacts/embedding/registry.d.ts +6 -11
- package/nodejs-artifacts/index.d.ts +51 -3
- package/nodejs-artifacts/index.js +28 -4
- package/nodejs-artifacts/merge.d.ts +54 -0
- package/nodejs-artifacts/merge.js +64 -0
- package/nodejs-artifacts/native.d.ts +29 -3
- package/nodejs-artifacts/native.js +26 -9
- package/nodejs-artifacts/query.d.ts +33 -10
- package/nodejs-artifacts/query.js +100 -13
- package/nodejs-artifacts/remote/client.d.ts +28 -0
- package/nodejs-artifacts/remote/client.js +172 -0
- package/nodejs-artifacts/remote/connection.d.ts +25 -0
- package/nodejs-artifacts/remote/connection.js +110 -0
- package/nodejs-artifacts/remote/index.d.ts +3 -0
- package/nodejs-artifacts/remote/index.js +9 -0
- package/nodejs-artifacts/remote/table.d.ts +42 -0
- package/nodejs-artifacts/remote/table.js +179 -0
- package/nodejs-artifacts/sanitize.d.ts +3 -2
- package/nodejs-artifacts/sanitize.js +55 -1
- package/nodejs-artifacts/table.d.ts +105 -30
- package/nodejs-artifacts/table.js +94 -237
- package/nodejs-artifacts/util.d.ts +14 -0
- package/nodejs-artifacts/util.js +65 -0
- package/package.json +25 -11
package/lancedb/table.ts
CHANGED
|
@@ -17,20 +17,30 @@ import {
|
|
|
17
17
|
Data,
|
|
18
18
|
IntoVector,
|
|
19
19
|
Schema,
|
|
20
|
+
TableLike,
|
|
20
21
|
fromDataToBuffer,
|
|
22
|
+
fromTableToBuffer,
|
|
23
|
+
fromTableToStreamBuffer,
|
|
24
|
+
isArrowTable,
|
|
25
|
+
makeArrowTable,
|
|
21
26
|
tableFromIPC,
|
|
22
27
|
} from "./arrow";
|
|
28
|
+
import { CreateTableOptions } from "./connection";
|
|
23
29
|
|
|
24
30
|
import { EmbeddingFunctionConfig, getRegistry } from "./embedding/registry";
|
|
25
31
|
import { IndexOptions } from "./indices";
|
|
32
|
+
import { MergeInsertBuilder } from "./merge";
|
|
26
33
|
import {
|
|
27
34
|
AddColumnsSql,
|
|
28
35
|
ColumnAlteration,
|
|
29
36
|
IndexConfig,
|
|
37
|
+
IndexStatistics,
|
|
30
38
|
OptimizeStats,
|
|
31
39
|
Table as _NativeTable,
|
|
32
40
|
} from "./native";
|
|
33
41
|
import { Query, VectorQuery } from "./query";
|
|
42
|
+
import { sanitizeTable } from "./sanitize";
|
|
43
|
+
import { IntoSql, toSQL } from "./util";
|
|
34
44
|
export { IndexConfig } from "./native";
|
|
35
45
|
|
|
36
46
|
/**
|
|
@@ -88,19 +98,15 @@ export interface OptimizeOptions {
|
|
|
88
98
|
* Closing a table is optional. It not closed, it will be closed when it is garbage
|
|
89
99
|
* collected.
|
|
90
100
|
*/
|
|
91
|
-
export class Table {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
/** Construct a Table. Internal use only. */
|
|
95
|
-
constructor(inner: _NativeTable) {
|
|
96
|
-
this.inner = inner;
|
|
101
|
+
export abstract class Table {
|
|
102
|
+
[Symbol.for("nodejs.util.inspect.custom")](): string {
|
|
103
|
+
return this.display();
|
|
97
104
|
}
|
|
105
|
+
/** Returns the name of the table */
|
|
106
|
+
abstract get name(): string;
|
|
98
107
|
|
|
99
108
|
/** Return true if the table has not been closed */
|
|
100
|
-
isOpen(): boolean
|
|
101
|
-
return this.inner.isOpen();
|
|
102
|
-
}
|
|
103
|
-
|
|
109
|
+
abstract isOpen(): boolean;
|
|
104
110
|
/**
|
|
105
111
|
* Close the table, releasing any underlying resources.
|
|
106
112
|
*
|
|
@@ -108,48 +114,44 @@ export class Table {
|
|
|
108
114
|
*
|
|
109
115
|
* Any attempt to use the table after it is closed will result in an error.
|
|
110
116
|
*/
|
|
111
|
-
close(): void
|
|
112
|
-
this.inner.close();
|
|
113
|
-
}
|
|
114
|
-
|
|
117
|
+
abstract close(): void;
|
|
115
118
|
/** Return a brief description of the table */
|
|
116
|
-
display(): string
|
|
117
|
-
return this.inner.display();
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
async #getEmbeddingFunctions(): Promise<
|
|
121
|
-
Map<string, EmbeddingFunctionConfig>
|
|
122
|
-
> {
|
|
123
|
-
const schema = await this.schema();
|
|
124
|
-
const registry = getRegistry();
|
|
125
|
-
return registry.parseFunctions(schema.metadata);
|
|
126
|
-
}
|
|
127
|
-
|
|
119
|
+
abstract display(): string;
|
|
128
120
|
/** Get the schema of the table. */
|
|
129
|
-
|
|
130
|
-
const schemaBuf = await this.inner.schema();
|
|
131
|
-
const tbl = tableFromIPC(schemaBuf);
|
|
132
|
-
return tbl.schema;
|
|
133
|
-
}
|
|
134
|
-
|
|
121
|
+
abstract schema(): Promise<Schema>;
|
|
135
122
|
/**
|
|
136
123
|
* Insert records into this Table.
|
|
137
124
|
* @param {Data} data Records to be inserted into the Table
|
|
138
125
|
*/
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
126
|
+
abstract add(data: Data, options?: Partial<AddDataOptions>): Promise<void>;
|
|
127
|
+
/**
|
|
128
|
+
* Update existing records in the Table
|
|
129
|
+
* @param opts.values The values to update. The keys are the column names and the values
|
|
130
|
+
* are the values to set.
|
|
131
|
+
* @example
|
|
132
|
+
* ```ts
|
|
133
|
+
* table.update({where:"x = 2", values:{"vector": [10, 10]}})
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
abstract update(
|
|
137
|
+
opts: {
|
|
138
|
+
values: Map<string, IntoSql> | Record<string, IntoSql>;
|
|
139
|
+
} & Partial<UpdateOptions>,
|
|
140
|
+
): Promise<void>;
|
|
141
|
+
/**
|
|
142
|
+
* Update existing records in the Table
|
|
143
|
+
* @param opts.valuesSql The values to update. The keys are the column names and the values
|
|
144
|
+
* are the values to set. The values are SQL expressions.
|
|
145
|
+
* @example
|
|
146
|
+
* ```ts
|
|
147
|
+
* table.update({where:"x = 2", valuesSql:{"x": "x + 1"}})
|
|
148
|
+
* ```
|
|
149
|
+
*/
|
|
150
|
+
abstract update(
|
|
151
|
+
opts: {
|
|
152
|
+
valuesSql: Map<string, string> | Record<string, string>;
|
|
153
|
+
} & Partial<UpdateOptions>,
|
|
154
|
+
): Promise<void>;
|
|
153
155
|
/**
|
|
154
156
|
* Update existing records in the Table
|
|
155
157
|
*
|
|
@@ -175,30 +177,15 @@ export class Table {
|
|
|
175
177
|
* @param {Partial<UpdateOptions>} options - additional options to control
|
|
176
178
|
* the update behavior
|
|
177
179
|
*/
|
|
178
|
-
|
|
180
|
+
abstract update(
|
|
179
181
|
updates: Map<string, string> | Record<string, string>,
|
|
180
182
|
options?: Partial<UpdateOptions>,
|
|
181
|
-
)
|
|
182
|
-
const onlyIf = options?.where;
|
|
183
|
-
let columns: [string, string][];
|
|
184
|
-
if (updates instanceof Map) {
|
|
185
|
-
columns = Array.from(updates.entries());
|
|
186
|
-
} else {
|
|
187
|
-
columns = Object.entries(updates);
|
|
188
|
-
}
|
|
189
|
-
await this.inner.update(onlyIf, columns);
|
|
190
|
-
}
|
|
183
|
+
): Promise<void>;
|
|
191
184
|
|
|
192
185
|
/** Count the total number of rows in the dataset. */
|
|
193
|
-
|
|
194
|
-
return await this.inner.countRows(filter);
|
|
195
|
-
}
|
|
196
|
-
|
|
186
|
+
abstract countRows(filter?: string): Promise<number>;
|
|
197
187
|
/** Delete the rows that satisfy the predicate. */
|
|
198
|
-
|
|
199
|
-
await this.inner.delete(predicate);
|
|
200
|
-
}
|
|
201
|
-
|
|
188
|
+
abstract delete(predicate: string): Promise<void>;
|
|
202
189
|
/**
|
|
203
190
|
* Create an index to speed up queries.
|
|
204
191
|
*
|
|
@@ -206,6 +193,9 @@ export class Table {
|
|
|
206
193
|
* Indices on vector columns will speed up vector searches.
|
|
207
194
|
* Indices on scalar columns will speed up filtering (in both
|
|
208
195
|
* vector and non-vector searches)
|
|
196
|
+
*
|
|
197
|
+
* @note We currently don't support custom named indexes,
|
|
198
|
+
* The index name will always be `${column}_idx`
|
|
209
199
|
* @example
|
|
210
200
|
* // If the column has a vector (fixed size list) data type then
|
|
211
201
|
* // an IvfPq vector index will be created.
|
|
@@ -225,13 +215,10 @@ export class Table {
|
|
|
225
215
|
* // Or create a Scalar index
|
|
226
216
|
* await table.createIndex("my_float_col");
|
|
227
217
|
*/
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
await this.inner.createIndex(nativeIndex, column, options?.replace);
|
|
233
|
-
}
|
|
234
|
-
|
|
218
|
+
abstract createIndex(
|
|
219
|
+
column: string,
|
|
220
|
+
options?: Partial<IndexOptions>,
|
|
221
|
+
): Promise<void>;
|
|
235
222
|
/**
|
|
236
223
|
* Create a {@link Query} Builder.
|
|
237
224
|
*
|
|
@@ -282,44 +269,20 @@ export class Table {
|
|
|
282
269
|
* }
|
|
283
270
|
* @returns {Query} A builder that can be used to parameterize the query
|
|
284
271
|
*/
|
|
285
|
-
query(): Query
|
|
286
|
-
return new Query(this.inner);
|
|
287
|
-
}
|
|
288
|
-
|
|
272
|
+
abstract query(): Query;
|
|
289
273
|
/**
|
|
290
274
|
* Create a search query to find the nearest neighbors
|
|
291
275
|
* of the given query vector
|
|
292
276
|
* @param {string} query - the query. This will be converted to a vector using the table's provided embedding function
|
|
293
|
-
* @
|
|
277
|
+
* @note If no embedding functions are defined in the table, this will error when collecting the results.
|
|
294
278
|
*/
|
|
295
|
-
search(query: string):
|
|
279
|
+
abstract search(query: string): VectorQuery;
|
|
296
280
|
/**
|
|
297
281
|
* Create a search query to find the nearest neighbors
|
|
298
282
|
* of the given query vector
|
|
299
283
|
* @param {IntoVector} query - the query vector
|
|
300
284
|
*/
|
|
301
|
-
search(query: IntoVector): VectorQuery;
|
|
302
|
-
search(query: string | IntoVector): Promise<VectorQuery> | VectorQuery {
|
|
303
|
-
if (typeof query !== "string") {
|
|
304
|
-
return this.vectorSearch(query);
|
|
305
|
-
} else {
|
|
306
|
-
return this.#getEmbeddingFunctions().then(async (functions) => {
|
|
307
|
-
// TODO: Support multiple embedding functions
|
|
308
|
-
const embeddingFunc: EmbeddingFunctionConfig | undefined = functions
|
|
309
|
-
.values()
|
|
310
|
-
.next().value;
|
|
311
|
-
if (!embeddingFunc) {
|
|
312
|
-
return Promise.reject(
|
|
313
|
-
new Error("No embedding functions are defined in the table"),
|
|
314
|
-
);
|
|
315
|
-
}
|
|
316
|
-
const embeddings =
|
|
317
|
-
await embeddingFunc.function.computeQueryEmbeddings(query);
|
|
318
|
-
return this.query().nearestTo(embeddings);
|
|
319
|
-
});
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
|
|
285
|
+
abstract search(query: IntoVector): VectorQuery;
|
|
323
286
|
/**
|
|
324
287
|
* Search the table with a given query vector.
|
|
325
288
|
*
|
|
@@ -327,11 +290,7 @@ export class Table {
|
|
|
327
290
|
* is the same thing as calling `nearestTo` on the builder returned
|
|
328
291
|
* by `query`. @see {@link Query#nearestTo} for more details.
|
|
329
292
|
*/
|
|
330
|
-
vectorSearch(vector: IntoVector): VectorQuery
|
|
331
|
-
return this.query().nearestTo(vector);
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
// TODO: Support BatchUDF
|
|
293
|
+
abstract vectorSearch(vector: IntoVector): VectorQuery;
|
|
335
294
|
/**
|
|
336
295
|
* Add new columns with defined values.
|
|
337
296
|
* @param {AddColumnsSql[]} newColumnTransforms pairs of column names and
|
|
@@ -339,19 +298,14 @@ export class Table {
|
|
|
339
298
|
* expressions will be evaluated for each row in the table, and can
|
|
340
299
|
* reference existing columns in the table.
|
|
341
300
|
*/
|
|
342
|
-
|
|
343
|
-
await this.inner.addColumns(newColumnTransforms);
|
|
344
|
-
}
|
|
301
|
+
abstract addColumns(newColumnTransforms: AddColumnsSql[]): Promise<void>;
|
|
345
302
|
|
|
346
303
|
/**
|
|
347
304
|
* Alter the name or nullability of columns.
|
|
348
305
|
* @param {ColumnAlteration[]} columnAlterations One or more alterations to
|
|
349
306
|
* apply to columns.
|
|
350
307
|
*/
|
|
351
|
-
|
|
352
|
-
await this.inner.alterColumns(columnAlterations);
|
|
353
|
-
}
|
|
354
|
-
|
|
308
|
+
abstract alterColumns(columnAlterations: ColumnAlteration[]): Promise<void>;
|
|
355
309
|
/**
|
|
356
310
|
* Drop one or more columns from the dataset
|
|
357
311
|
*
|
|
@@ -363,15 +317,10 @@ export class Table {
|
|
|
363
317
|
* be nested column references (e.g. "a.b.c") or top-level column names
|
|
364
318
|
* (e.g. "a").
|
|
365
319
|
*/
|
|
366
|
-
|
|
367
|
-
await this.inner.dropColumns(columnNames);
|
|
368
|
-
}
|
|
369
|
-
|
|
320
|
+
abstract dropColumns(columnNames: string[]): Promise<void>;
|
|
370
321
|
/** Retrieve the version of the table */
|
|
371
|
-
async version(): Promise<number> {
|
|
372
|
-
return await this.inner.version();
|
|
373
|
-
}
|
|
374
322
|
|
|
323
|
+
abstract version(): Promise<number>;
|
|
375
324
|
/**
|
|
376
325
|
* Checks out a specific version of the table _This is an in-place operation._
|
|
377
326
|
*
|
|
@@ -397,19 +346,14 @@ export class Table {
|
|
|
397
346
|
* console.log(await table.version()); // 2
|
|
398
347
|
* ```
|
|
399
348
|
*/
|
|
400
|
-
|
|
401
|
-
await this.inner.checkout(version);
|
|
402
|
-
}
|
|
403
|
-
|
|
349
|
+
abstract checkout(version: number): Promise<void>;
|
|
404
350
|
/**
|
|
405
351
|
* Checkout the latest version of the table. _This is an in-place operation._
|
|
406
352
|
*
|
|
407
353
|
* The table will be set back into standard mode, and will track the latest
|
|
408
354
|
* version of the table.
|
|
409
355
|
*/
|
|
410
|
-
|
|
411
|
-
await this.inner.checkoutLatest();
|
|
412
|
-
}
|
|
356
|
+
abstract checkoutLatest(): Promise<void>;
|
|
413
357
|
|
|
414
358
|
/**
|
|
415
359
|
* Restore the table to the currently checked out version
|
|
@@ -423,10 +367,7 @@ export class Table {
|
|
|
423
367
|
* Once the operation concludes the table will no longer be in a checked
|
|
424
368
|
* out state and the read_consistency_interval, if any, will apply.
|
|
425
369
|
*/
|
|
426
|
-
|
|
427
|
-
await this.inner.restore();
|
|
428
|
-
}
|
|
429
|
-
|
|
370
|
+
abstract restore(): Promise<void>;
|
|
430
371
|
/**
|
|
431
372
|
* Optimize the on-disk data and indices for better performance.
|
|
432
373
|
*
|
|
@@ -457,6 +398,243 @@ export class Table {
|
|
|
457
398
|
* you have added or modified 100,000 or more records or run more than 20 data
|
|
458
399
|
* modification operations.
|
|
459
400
|
*/
|
|
401
|
+
abstract optimize(options?: Partial<OptimizeOptions>): Promise<OptimizeStats>;
|
|
402
|
+
/** List all indices that have been created with {@link Table.createIndex} */
|
|
403
|
+
abstract listIndices(): Promise<IndexConfig[]>;
|
|
404
|
+
/** Return the table as an arrow table */
|
|
405
|
+
abstract toArrow(): Promise<ArrowTable>;
|
|
406
|
+
|
|
407
|
+
abstract mergeInsert(on: string | string[]): MergeInsertBuilder;
|
|
408
|
+
|
|
409
|
+
/** List all the stats of a specified index
|
|
410
|
+
*
|
|
411
|
+
* @param {string} name The name of the index.
|
|
412
|
+
* @returns {IndexStatistics | undefined} The stats of the index. If the index does not exist, it will return undefined
|
|
413
|
+
*/
|
|
414
|
+
abstract indexStats(name: string): Promise<IndexStatistics | undefined>;
|
|
415
|
+
|
|
416
|
+
static async parseTableData(
|
|
417
|
+
data: Record<string, unknown>[] | TableLike,
|
|
418
|
+
options?: Partial<CreateTableOptions>,
|
|
419
|
+
streaming = false,
|
|
420
|
+
) {
|
|
421
|
+
let mode: string = options?.mode ?? "create";
|
|
422
|
+
const existOk = options?.existOk ?? false;
|
|
423
|
+
|
|
424
|
+
if (mode === "create" && existOk) {
|
|
425
|
+
mode = "exist_ok";
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
let table: ArrowTable;
|
|
429
|
+
if (isArrowTable(data)) {
|
|
430
|
+
table = sanitizeTable(data);
|
|
431
|
+
} else {
|
|
432
|
+
table = makeArrowTable(data as Record<string, unknown>[], options);
|
|
433
|
+
}
|
|
434
|
+
if (streaming) {
|
|
435
|
+
const buf = await fromTableToStreamBuffer(
|
|
436
|
+
table,
|
|
437
|
+
options?.embeddingFunction,
|
|
438
|
+
options?.schema,
|
|
439
|
+
);
|
|
440
|
+
return { buf, mode };
|
|
441
|
+
} else {
|
|
442
|
+
const buf = await fromTableToBuffer(
|
|
443
|
+
table,
|
|
444
|
+
options?.embeddingFunction,
|
|
445
|
+
options?.schema,
|
|
446
|
+
);
|
|
447
|
+
return { buf, mode };
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
export class LocalTable extends Table {
|
|
453
|
+
private readonly inner: _NativeTable;
|
|
454
|
+
|
|
455
|
+
constructor(inner: _NativeTable) {
|
|
456
|
+
super();
|
|
457
|
+
this.inner = inner;
|
|
458
|
+
}
|
|
459
|
+
get name(): string {
|
|
460
|
+
return this.inner.name;
|
|
461
|
+
}
|
|
462
|
+
isOpen(): boolean {
|
|
463
|
+
return this.inner.isOpen();
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
close(): void {
|
|
467
|
+
this.inner.close();
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
display(): string {
|
|
471
|
+
return this.inner.display();
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
private async getEmbeddingFunctions(): Promise<
|
|
475
|
+
Map<string, EmbeddingFunctionConfig>
|
|
476
|
+
> {
|
|
477
|
+
const schema = await this.schema();
|
|
478
|
+
const registry = getRegistry();
|
|
479
|
+
return registry.parseFunctions(schema.metadata);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/** Get the schema of the table. */
|
|
483
|
+
async schema(): Promise<Schema> {
|
|
484
|
+
const schemaBuf = await this.inner.schema();
|
|
485
|
+
const tbl = tableFromIPC(schemaBuf);
|
|
486
|
+
return tbl.schema;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
async add(data: Data, options?: Partial<AddDataOptions>): Promise<void> {
|
|
490
|
+
const mode = options?.mode ?? "append";
|
|
491
|
+
const schema = await this.schema();
|
|
492
|
+
const registry = getRegistry();
|
|
493
|
+
const functions = registry.parseFunctions(schema.metadata);
|
|
494
|
+
|
|
495
|
+
const buffer = await fromDataToBuffer(
|
|
496
|
+
data,
|
|
497
|
+
functions.values().next().value,
|
|
498
|
+
schema,
|
|
499
|
+
);
|
|
500
|
+
await this.inner.add(buffer, mode);
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
async update(
|
|
504
|
+
optsOrUpdates:
|
|
505
|
+
| (Map<string, string> | Record<string, string>)
|
|
506
|
+
| ({
|
|
507
|
+
values: Map<string, IntoSql> | Record<string, IntoSql>;
|
|
508
|
+
} & Partial<UpdateOptions>)
|
|
509
|
+
| ({
|
|
510
|
+
valuesSql: Map<string, string> | Record<string, string>;
|
|
511
|
+
} & Partial<UpdateOptions>),
|
|
512
|
+
options?: Partial<UpdateOptions>,
|
|
513
|
+
) {
|
|
514
|
+
const isValues =
|
|
515
|
+
"values" in optsOrUpdates && typeof optsOrUpdates.values !== "string";
|
|
516
|
+
const isValuesSql =
|
|
517
|
+
"valuesSql" in optsOrUpdates &&
|
|
518
|
+
typeof optsOrUpdates.valuesSql !== "string";
|
|
519
|
+
const isMap = (obj: unknown): obj is Map<string, string> => {
|
|
520
|
+
return obj instanceof Map;
|
|
521
|
+
};
|
|
522
|
+
|
|
523
|
+
let predicate;
|
|
524
|
+
let columns: [string, string][];
|
|
525
|
+
switch (true) {
|
|
526
|
+
case isMap(optsOrUpdates):
|
|
527
|
+
columns = Array.from(optsOrUpdates.entries());
|
|
528
|
+
predicate = options?.where;
|
|
529
|
+
break;
|
|
530
|
+
case isValues && isMap(optsOrUpdates.values):
|
|
531
|
+
columns = Array.from(optsOrUpdates.values.entries()).map(([k, v]) => [
|
|
532
|
+
k,
|
|
533
|
+
toSQL(v),
|
|
534
|
+
]);
|
|
535
|
+
predicate = optsOrUpdates.where;
|
|
536
|
+
break;
|
|
537
|
+
case isValues && !isMap(optsOrUpdates.values):
|
|
538
|
+
columns = Object.entries(optsOrUpdates.values).map(([k, v]) => [
|
|
539
|
+
k,
|
|
540
|
+
toSQL(v),
|
|
541
|
+
]);
|
|
542
|
+
predicate = optsOrUpdates.where;
|
|
543
|
+
break;
|
|
544
|
+
|
|
545
|
+
case isValuesSql && isMap(optsOrUpdates.valuesSql):
|
|
546
|
+
columns = Array.from(optsOrUpdates.valuesSql.entries());
|
|
547
|
+
predicate = optsOrUpdates.where;
|
|
548
|
+
break;
|
|
549
|
+
case isValuesSql && !isMap(optsOrUpdates.valuesSql):
|
|
550
|
+
columns = Object.entries(optsOrUpdates.valuesSql).map(([k, v]) => [
|
|
551
|
+
k,
|
|
552
|
+
v,
|
|
553
|
+
]);
|
|
554
|
+
predicate = optsOrUpdates.where;
|
|
555
|
+
break;
|
|
556
|
+
default:
|
|
557
|
+
columns = Object.entries(optsOrUpdates as Record<string, string>);
|
|
558
|
+
predicate = options?.where;
|
|
559
|
+
}
|
|
560
|
+
await this.inner.update(predicate, columns);
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
async countRows(filter?: string): Promise<number> {
|
|
564
|
+
return await this.inner.countRows(filter);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
async delete(predicate: string): Promise<void> {
|
|
568
|
+
await this.inner.delete(predicate);
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
async createIndex(column: string, options?: Partial<IndexOptions>) {
|
|
572
|
+
// Bit of a hack to get around the fact that TS has no package-scope.
|
|
573
|
+
// biome-ignore lint/suspicious/noExplicitAny: skip
|
|
574
|
+
const nativeIndex = (options?.config as any)?.inner;
|
|
575
|
+
await this.inner.createIndex(nativeIndex, column, options?.replace);
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
query(): Query {
|
|
579
|
+
return new Query(this.inner);
|
|
580
|
+
}
|
|
581
|
+
search(query: string | IntoVector): VectorQuery {
|
|
582
|
+
if (typeof query !== "string") {
|
|
583
|
+
return this.vectorSearch(query);
|
|
584
|
+
} else {
|
|
585
|
+
const queryPromise = this.getEmbeddingFunctions().then(
|
|
586
|
+
async (functions) => {
|
|
587
|
+
// TODO: Support multiple embedding functions
|
|
588
|
+
const embeddingFunc: EmbeddingFunctionConfig | undefined = functions
|
|
589
|
+
.values()
|
|
590
|
+
.next().value;
|
|
591
|
+
if (!embeddingFunc) {
|
|
592
|
+
return Promise.reject(
|
|
593
|
+
new Error("No embedding functions are defined in the table"),
|
|
594
|
+
);
|
|
595
|
+
}
|
|
596
|
+
return await embeddingFunc.function.computeQueryEmbeddings(query);
|
|
597
|
+
},
|
|
598
|
+
);
|
|
599
|
+
|
|
600
|
+
return this.query().nearestTo(queryPromise);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
vectorSearch(vector: IntoVector): VectorQuery {
|
|
605
|
+
return this.query().nearestTo(vector);
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
// TODO: Support BatchUDF
|
|
609
|
+
|
|
610
|
+
async addColumns(newColumnTransforms: AddColumnsSql[]): Promise<void> {
|
|
611
|
+
await this.inner.addColumns(newColumnTransforms);
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
async alterColumns(columnAlterations: ColumnAlteration[]): Promise<void> {
|
|
615
|
+
await this.inner.alterColumns(columnAlterations);
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
async dropColumns(columnNames: string[]): Promise<void> {
|
|
619
|
+
await this.inner.dropColumns(columnNames);
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
async version(): Promise<number> {
|
|
623
|
+
return await this.inner.version();
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
async checkout(version: number): Promise<void> {
|
|
627
|
+
await this.inner.checkout(version);
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
async checkoutLatest(): Promise<void> {
|
|
631
|
+
await this.inner.checkoutLatest();
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
async restore(): Promise<void> {
|
|
635
|
+
await this.inner.restore();
|
|
636
|
+
}
|
|
637
|
+
|
|
460
638
|
async optimize(options?: Partial<OptimizeOptions>): Promise<OptimizeStats> {
|
|
461
639
|
let cleanupOlderThanMs;
|
|
462
640
|
if (
|
|
@@ -469,13 +647,23 @@ export class Table {
|
|
|
469
647
|
return await this.inner.optimize(cleanupOlderThanMs);
|
|
470
648
|
}
|
|
471
649
|
|
|
472
|
-
/** List all indices that have been created with {@link Table.createIndex} */
|
|
473
650
|
async listIndices(): Promise<IndexConfig[]> {
|
|
474
651
|
return await this.inner.listIndices();
|
|
475
652
|
}
|
|
476
653
|
|
|
477
|
-
/** Return the table as an arrow table */
|
|
478
654
|
async toArrow(): Promise<ArrowTable> {
|
|
479
655
|
return await this.query().toArrow();
|
|
480
656
|
}
|
|
657
|
+
|
|
658
|
+
async indexStats(name: string): Promise<IndexStatistics | undefined> {
|
|
659
|
+
const stats = await this.inner.indexStats(name);
|
|
660
|
+
if (stats === null) {
|
|
661
|
+
return undefined;
|
|
662
|
+
}
|
|
663
|
+
return stats;
|
|
664
|
+
}
|
|
665
|
+
mergeInsert(on: string | string[]): MergeInsertBuilder {
|
|
666
|
+
on = Array.isArray(on) ? on : [on];
|
|
667
|
+
return new MergeInsertBuilder(this.inner.mergeInsert(on));
|
|
668
|
+
}
|
|
481
669
|
}
|
package/lancedb/util.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export type IntoSql =
|
|
2
|
+
| string
|
|
3
|
+
| number
|
|
4
|
+
| boolean
|
|
5
|
+
| null
|
|
6
|
+
| Date
|
|
7
|
+
| ArrayBufferLike
|
|
8
|
+
| Buffer
|
|
9
|
+
| IntoSql[];
|
|
10
|
+
|
|
11
|
+
export function toSQL(value: IntoSql): string {
|
|
12
|
+
if (typeof value === "string") {
|
|
13
|
+
return `'${value.replace(/'/g, "''")}'`;
|
|
14
|
+
} else if (typeof value === "number") {
|
|
15
|
+
return value.toString();
|
|
16
|
+
} else if (typeof value === "boolean") {
|
|
17
|
+
return value ? "TRUE" : "FALSE";
|
|
18
|
+
} else if (value === null) {
|
|
19
|
+
return "NULL";
|
|
20
|
+
} else if (value instanceof Date) {
|
|
21
|
+
return `'${value.toISOString()}'`;
|
|
22
|
+
} else if (Array.isArray(value)) {
|
|
23
|
+
return `[${value.map(toSQL).join(", ")}]`;
|
|
24
|
+
} else if (Buffer.isBuffer(value)) {
|
|
25
|
+
return `X'${value.toString("hex")}'`;
|
|
26
|
+
} else if (value instanceof ArrayBuffer) {
|
|
27
|
+
return `X'${Buffer.from(value).toString("hex")}'`;
|
|
28
|
+
} else {
|
|
29
|
+
throw new Error(
|
|
30
|
+
`Unsupported value type: ${typeof value} value: (${value})`,
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export class TTLCache {
|
|
36
|
+
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
|
37
|
+
private readonly cache: Map<string, { value: any; expires: number }>;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @param ttl Time to live in milliseconds
|
|
41
|
+
*/
|
|
42
|
+
constructor(private readonly ttl: number) {
|
|
43
|
+
this.cache = new Map();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
|
47
|
+
get(key: string): any | undefined {
|
|
48
|
+
const entry = this.cache.get(key);
|
|
49
|
+
if (entry === undefined) {
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (entry.expires < Date.now()) {
|
|
54
|
+
this.cache.delete(key);
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return entry.value;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
|
62
|
+
set(key: string, value: any): void {
|
|
63
|
+
this.cache.set(key, { value, expires: Date.now() + this.ttl });
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
delete(key: string): void {
|
|
67
|
+
this.cache.delete(key);
|
|
68
|
+
}
|
|
69
|
+
}
|