mirror of
https://github.com/lancedb/lancedb.git
synced 2026-10-26 21:46:15 +00:00
feat!: return lazy iterators for table and namespace listings (#4599)
Make table and namespace listings consistent with other resource
listings across Rust, Python, and TypeScript. Callers can iterate over
individual names across all pages, with configurable page sizes and
continuation tokens.
In order to avoid breaking existing Python users, this change adds some
compatibility methods to the returned Python iterators. Code such as:
```
for t in db.list_tables().tables:
print(t)
```
will continue to work as expected because the iterator has a `tables`
field and a `page_token` field, which function as expected to reveal the
first page of results. In other words, it is never necessary to use the
iterator __as an iterator__. It may be used as if it were an old-style
response object. (As the iterator progresses, the `tables` list may
switch to the second, third, etc. page of results.) Similar
compatibility code allows the async python API to keep working as well.
This commit is contained in:
@@ -4,6 +4,12 @@ import { afterEach, describe, expect, jest, test } from "@jest/globals";
|
||||
import * as lancedb from "@lancedb/lancedb";
|
||||
import { withTempDirectory } from "./util.ts";
|
||||
|
||||
async function collectNames(items: AsyncIterable<string>): Promise<string[]> {
|
||||
const names: string[] = [];
|
||||
for await (const name of items) names.push(name);
|
||||
return names;
|
||||
}
|
||||
|
||||
test("connect to a local database", async () => {
|
||||
await withTempDirectory(async (tempDir) => {
|
||||
const cwd = process.cwd();
|
||||
@@ -13,12 +19,12 @@ test("connect to a local database", async () => {
|
||||
const db = await lancedb.connect("ex_lancedb");
|
||||
// --8<-- [end:connect]
|
||||
await db.createTable("probe", [{ id: 1 }]);
|
||||
expect((await db.listTables()).tables).toEqual(["probe"]);
|
||||
expect(await collectNames(db.listTables())).toEqual(["probe"]);
|
||||
} finally {
|
||||
process.chdir(cwd);
|
||||
}
|
||||
const reopened = await lancedb.connect(`${tempDir}/ex_lancedb`);
|
||||
expect((await reopened.listTables()).tables).toEqual(["probe"]);
|
||||
expect(await collectNames(reopened.listTables())).toEqual(["probe"]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -109,8 +115,8 @@ async function namespaceTableOpsExample() {
|
||||
);
|
||||
|
||||
// Verify
|
||||
console.log((await db.listNamespaces()).namespaces); // ["prod"]
|
||||
console.log((await db.listNamespaces(["prod"])).namespaces); // ["recommendations", "search"]
|
||||
console.log(await collectNames(db.listNamespaces())); // ["prod"]
|
||||
console.log(await collectNames(db.listNamespaces(["prod"]))); // ["recommendations", "search"]
|
||||
console.log(await db.tableNames(["prod", "search"])); // ["user"]
|
||||
console.log(await db.tableNames(["prod", "recommendations"])); // ["user"]
|
||||
// --8<-- [end:namespace_table_ops]
|
||||
@@ -124,7 +130,7 @@ async function namespaceAdminOpsExample() {
|
||||
await db.createNamespace(["prod"]);
|
||||
await db.createNamespace(["prod", "search"]);
|
||||
|
||||
const childNamespaces = (await db.listNamespaces(["prod"])).namespaces;
|
||||
const childNamespaces = await collectNames(db.listNamespaces(["prod"]));
|
||||
console.log(`Child namespaces under ${JSON.stringify(namespace)}:`, childNamespaces);
|
||||
// Child namespaces under ["prod","search"]: [ 'search' ]
|
||||
|
||||
|
||||
@@ -20,12 +20,7 @@ const connections =
|
||||
|
||||
async function tableNames(db: lancedb.Connection) {
|
||||
const names: string[] = [];
|
||||
let pageToken: string | undefined;
|
||||
do {
|
||||
const page = await db.listTables({ pageToken });
|
||||
names.push(...page.tables);
|
||||
pageToken = page.pageToken;
|
||||
} while (pageToken);
|
||||
for await (const name of db.listTables()) names.push(name);
|
||||
return names;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user