fix(node): route auto search using table embeddings

This commit is contained in:
Gatefixer
2026-08-06 01:25:57 +00:00
parent 7357d63e87
commit 4d3abb7db7
4 changed files with 49 additions and 10 deletions
+18 -1
View File
@@ -2298,7 +2298,24 @@ describe.each([arrow15, arrow16, arrow17, arrow18])(
);
});
test("full text search if no embedding function provided", async () => {
test("full text search if only an unrelated embedding function is registered", async () => {
register("unused")(
class extends EmbeddingFunction<string> {
ndims() {
return 3;
}
embeddingDataType() {
return new Float32();
}
async computeQueryEmbeddings(_data: string) {
return [1, 2, 3];
}
async computeSourceEmbeddings(data: string[]) {
return data.map(() => [1, 2, 3]);
}
},
);
const db = await connect(tmpDir.name);
const data = [
{ text: "hello world", vector: [0.1, 0.2, 0.3] },
+4 -4
View File
@@ -535,7 +535,7 @@ export class LocalConnection extends Connection {
options?.indexCacheSize,
);
let table: Table = new LocalTable(innerTable);
let table: Table = await LocalTable.create(innerTable);
// "main" is the default branch, so treat it as no branch. On a real branch,
// scope and pin in one step (yielding "version V of branch B"); otherwise
// pin the version, if any, against main.
@@ -570,7 +570,7 @@ export class LocalConnection extends Connection {
options?.isShallow ?? true,
);
return new LocalTable(innerTable);
return await LocalTable.create(innerTable);
}
private getStorageOptions(
@@ -652,7 +652,7 @@ export class LocalConnection extends Connection {
storageOptions,
);
return new LocalTable(innerTable);
return await LocalTable.create(innerTable);
}
async createEmptyTable(
@@ -698,7 +698,7 @@ export class LocalConnection extends Connection {
namespacePath ?? [],
storageOptions,
);
return new LocalTable(innerTable);
return await LocalTable.create(innerTable);
}
async dropTable(name: string, namespacePath?: string[]): Promise<void> {
+1 -1
View File
@@ -172,7 +172,7 @@ export class PermutationBuilder {
*/
async execute(): Promise<Table> {
const nativeTable: NativeTable = await this.inner.execute();
return new LocalTable(nativeTable);
return await LocalTable.create(nativeTable);
}
}
+26 -4
View File
@@ -814,10 +814,30 @@ export abstract class Table {
export class LocalTable extends Table {
private readonly inner: _NativeTable;
private readonly hasEmbeddingFunctions: boolean;
constructor(inner: _NativeTable) {
private constructor(inner: _NativeTable, hasEmbeddingFunctions: boolean) {
super();
this.inner = inner;
this.hasEmbeddingFunctions = hasEmbeddingFunctions;
}
static async create(inner: _NativeTable): Promise<LocalTable> {
const schemaBuf = await inner.schema();
const schema = tableFromIPC(schemaBuf).schema;
const serializedFunctions = schema.metadata.get("embedding_functions");
let hasEmbeddingFunctions = false;
if (serializedFunctions !== undefined) {
try {
const functions: unknown = JSON.parse(serializedFunctions);
hasEmbeddingFunctions =
!Array.isArray(functions) || functions.length > 0;
} catch {
// Let parseFunctions report malformed metadata when the query executes.
hasEmbeddingFunctions = true;
}
}
return new LocalTable(inner, hasEmbeddingFunctions);
}
get name(): string {
return this.inner.name;
@@ -1038,7 +1058,7 @@ export class LocalTable extends Table {
// fall back to full text search if no embedding functions are defined and the query is a string
if (
queryType === "auto" &&
(getRegistry().length() === 0 || instanceOfFullTextQuery(query))
(!this.hasEmbeddingFunctions || instanceOfFullTextQuery(query))
) {
return this.query().fullTextSearch(query, {
columns: ftsColumns,
@@ -1461,7 +1481,9 @@ export class Branches {
fromRef?: string,
fromVersion?: number,
): Promise<Table> {
return new LocalTable(await this.#inner.create(name, fromRef, fromVersion));
return await LocalTable.create(
await this.#inner.create(name, fromRef, fromVersion),
);
}
/**
@@ -1472,7 +1494,7 @@ export class Branches {
* latest and stays writable.
*/
async checkout(name: string, version?: number): Promise<Table> {
return new LocalTable(await this.#inner.checkout(name, version));
return await LocalTable.create(await this.#inner.checkout(name, version));
}
/** Delete a branch. */