Skip to content

fix(lancedb): refresh the Tantivy FTS index so keyword_search sees later inserts - #87

Open
teddytennant wants to merge 1 commit into
aiming-lab:mainfrom
teddytennant:fix/lancedb-fts-refresh-after-insert
Open

teddytennant wants to merge 1 commit into
aiming-lab:mainfrom
teddytennant:fix/lancedb-fts-refresh-after-insert

Conversation

@teddytennant

Copy link
Copy Markdown

Fixes #78

LanceDBVectorStoreBackend built its Tantivy full text index once, on the first insert, and skipped it afterwards. Tantivy indexes are snapshots, so every entry added by a later insert was stored and visible to semantic and structured search but never returned by keyword_search. Since ingestion writes one batch per window, anything past the first window was affected. A table reopened in a new process had the same gap.

Changes:

  • insert() now only marks the index stale (local storage only).
  • keyword_search() rebuilds the index before querying when it is stale or missing. Rebuilding lazily means ingestion doesn't pay for a rebuild on every window.
  • The index build and the query run under a lock, since the retriever searches from a thread pool.
  • Cloud storage keeps building the native index once. I checked locally that the native index also searches rows added after it was created, but I couldn't test an actual gs:// or s3:// backend.

Tests added in tests/test_vector_store_backend.py cover entries from later inserts, reopening an existing table, clear() followed by inserts, and that rebuilds happen at search time rather than insert time. The first two and the lazy-rebuild test fail on main.

Notes:

  • FTS needs pylance installed alongside lancedb. Without it, index creation is skipped silently and keyword search returns nothing. I didn't touch requirements.txt.
  • The first keyword search after new inserts rebuilds the index, which grows with table size (about 0.15s up to ~6k rows in my timing). If you'd rather move local storage to the native index, that would change scoring and tokenization, so I left it out of this PR.
  • The same one-shot _fts_initialized pattern exists in cross/storage_lancedb.py and the two simplemem-skill copies of vector_store.py. I kept this PR focused on the core backend and can follow up on those.

…ter inserts

The local (Tantivy) full text index was built once, on the first insert,
and guarded by _fts_initialized afterwards. Tantivy indexes are snapshots,
so every row added by a later insert was stored and visible to semantic and
structured search but invisible to keyword_search. A table reopened by a new
process carried the same gap.

insert() now only marks the index stale (local storage only), and
keyword_search() rebuilds it before querying when it is stale or missing.
Rebuilding lazily keeps ingestion, which writes one batch per window, from
paying for a rebuild on every insert. The index build and the query share a
lock so concurrent searches do not rebuild or read the index mid-write.

The native index used for cloud storage already searches rows added after
it was created, so it is still built only once.

Fixes aiming-lab#78
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Full text index is built only once, so every entry inserted after the first batch is invisible to keyword_search

1 participant