From cdbf6e10293b0bbd71f559a75969fc44c77779f1 Mon Sep 17 00:00:00 2001 From: Gatefixer <313497061+lancedb-gatefixer[bot]@users.noreply.github.com> Date: Sat, 8 Aug 2026 12:34:43 +0000 Subject: [PATCH] fix(node): select auto search from table metadata --- nodejs/__test__/fixtures/auto_fts_search.cjs | 2 ++ nodejs/lancedb/connection.ts | 8 ++--- nodejs/lancedb/permutation.ts | 2 +- nodejs/lancedb/table.ts | 31 +++++++++++++++++--- 4 files changed, 34 insertions(+), 9 deletions(-) diff --git a/nodejs/__test__/fixtures/auto_fts_search.cjs b/nodejs/__test__/fixtures/auto_fts_search.cjs index 23bf6e3f0..b5ab060b3 100644 --- a/nodejs/__test__/fixtures/auto_fts_search.cjs +++ b/nodejs/__test__/fixtures/auto_fts_search.cjs @@ -9,6 +9,8 @@ const { getRegistry } = require("../../dist/embedding/registry"); async function main() { assert.equal(typeof embedding.getRegistry, "function"); assert.equal(getRegistry().length(), 0); + assert.equal(embedding.getRegistry(), getRegistry()); + assert.equal(getRegistry().length(), 2); const dir = tmp.dirSync({ unsafeCleanup: true }); let db; diff --git a/nodejs/lancedb/connection.ts b/nodejs/lancedb/connection.ts index e63a7ae65..9e930b5b4 100644 --- a/nodejs/lancedb/connection.ts +++ b/nodejs/lancedb/connection.ts @@ -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 LocalTable.create(innerTable); } private getStorageOptions( @@ -652,7 +652,7 @@ export class LocalConnection extends Connection { storageOptions, ); - return new LocalTable(innerTable); + return LocalTable.create(innerTable); } async createEmptyTable( @@ -698,7 +698,7 @@ export class LocalConnection extends Connection { namespacePath ?? [], storageOptions, ); - return new LocalTable(innerTable); + return LocalTable.create(innerTable); } async dropTable(name: string, namespacePath?: string[]): Promise { diff --git a/nodejs/lancedb/permutation.ts b/nodejs/lancedb/permutation.ts index e55b68553..79d9d7ebb 100644 --- a/nodejs/lancedb/permutation.ts +++ b/nodejs/lancedb/permutation.ts @@ -172,7 +172,7 @@ export class PermutationBuilder { */ async execute(): Promise { const nativeTable: NativeTable = await this.inner.execute(); - return new LocalTable(nativeTable); + return LocalTable.create(nativeTable); } } diff --git a/nodejs/lancedb/table.ts b/nodejs/lancedb/table.ts index 3359a2643..a3ac3d415 100644 --- a/nodejs/lancedb/table.ts +++ b/nodejs/lancedb/table.ts @@ -814,10 +814,31 @@ 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; + } + + /** @hidden */ + static async create(inner: _NativeTable): Promise { + const schemaBuf = await inner.schema(); + const schema = tableFromIPC(schemaBuf).schema; + const serializedFunctions = schema.metadata.get("embedding_functions"); + if (serializedFunctions === undefined) { + return new LocalTable(inner, false); + } + + let hasEmbeddingFunctions = true; + try { + const functions = JSON.parse(serializedFunctions); + hasEmbeddingFunctions = !Array.isArray(functions) || functions.length > 0; + } catch { + // Preserve the existing parse error when the search is executed. + } + return new LocalTable(inner, hasEmbeddingFunctions); } get name(): string { return this.inner.name; @@ -1038,7 +1059,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 +1482,9 @@ export class Branches { fromRef?: string, fromVersion?: number, ): Promise
{ - return new LocalTable(await this.#inner.create(name, fromRef, fromVersion)); + return LocalTable.create( + await this.#inner.create(name, fromRef, fromVersion), + ); } /** @@ -1472,7 +1495,7 @@ export class Branches { * latest and stays writable. */ async checkout(name: string, version?: number): Promise
{ - return new LocalTable(await this.#inner.checkout(name, version)); + return LocalTable.create(await this.#inner.checkout(name, version)); } /** Delete a branch. */