Skip to main content
A VectorTable is the handle returned by db.open(). It is where you add records, look them up by id or exact-match fields, and manage indexes. For ranked, query-based retrieval see Search. Every method that returns records is typed against your metadata, and every record has the shape { id, text, metadata }.
const table = await db.open("articles");

Adding records

add() inserts records. Each record needs an id, the text to embed and full-text index, and your metadata object. The text is embedded automatically — you never pass a vector.
await table.add([
  {
    id: "1",
    text: "An introduction to retrieval-augmented generation systems.",
    metadata: { title: "RAG Intro", category: "AI" },
  },
  {
    id: "2",
    text: "How vector databases store and search embeddings.",
    metadata: { title: "Vector DBs", category: "Database" },
  },
]);
add() returns the table, so calls can be chained.

Looking up records

These methods do exact-match lookups (no embedding or ranking). Use them when you already know the id or want rows matching specific field values.

findById()

Returns the single record with the given id, or null if none matches.
const article = await table.findById("1");
// { id: "1", text: "...", metadata: { title: "RAG Intro", category: "AI" } } | null
Pass select to return only certain columns. id is always included.
const article = await table.findById("1", { select: ["title", "category"] });

findBy()

Returns records that match an exact-match filter on metadata fields. Multiple fields are combined with AND; undefined values are ignored.
const articles = await table.findBy(
  { category: "AI" },
  { limit: 20, select: ["title"] },
);
OptionTypeDefaultDescription
limitnumber10Maximum records to return.
select(keyof metadata | "id" | "text")[]all columnsColumns to return; id is always included.

findOneBy()

Like findBy() but returns the first match or null.
const article = await table.findOneBy({ title: "RAG Intro" });
In findBy() / findOneBy(), the keys are your metadata field names — the package resolves them to the underlying metadata.<field> columns for you. The same applies to select and to filters.

Indexing

Tables created by open() already carry a btree index on id, a full-text index on text, and an IVF-PQ index on vector. These methods let you add or rebuild indexes — for example a scalar index on a metadata field you filter on often.

createIndex()

Creates a scalar index on a column. Choose the index type via config: btree (range and equality), bitmap (low-cardinality categories), or labelList (list membership).
import { Index } from "@lancedb/lancedb";

await table.createIndex("metadata.category", { config: Index.bitmap() });

createVectorIndex()

Creates an IVF-PQ vector index. Defaults to the vector column.
await table.createVectorIndex();
// or target a specific column
await table.createVectorIndex("vector");
Both methods return the table for chaining.
Build a scalar index on any metadata field you filter on frequently — it lets the query engine skip non-matching rows instead of scanning them, which speeds up both findBy() and filtered search.

Inspecting query plans

explainPlan() and analyzePlan() help you tune retrieval — they reveal which indexes are used and where time is spent. See Search → Inspecting query plans for details and examples.