Skip to content

Docs: rewrite search-by-meaning around a vec0 index instead of per-row embed() #1003

Closed

Description

@thekevinbot

Problem

docs/howto/search-by-meaning.md teaches semantic search as a path-table
subquery that embeds every matched file at query time:

SELECT path,
       vec_distance_cosine(emb, embed('how do I cook pasta?')) AS distance
FROM (SELECT path, embed(content) AS emb FROM './notes/*.md')
WHERE emb IS NOT NULL
ORDER BY distance
LIMIT 3

That is the only shape the guide teaches, and it costs one worker round trip
per matched file, per query
, on top of a path-table walk that re-reads every
file's content. The vector cache
removes the model inference on a repeat run — it does not remove the round
trip and it does not remove the walk.

Since #956 the alternative is expressible in config: a vec0 virtual table
declared in the same ddl batch as the row table, filled by a trigger calling
embed(). A query then embeds once (the query text) and vec0 does an
in-process KNN scan — the query-side effect #956 called out.

#994 added a ::: tip pointing at docs/reference/config.md#batch-ddl, but
left the guide's central example, and its whole narrative, on the per-row
shape.

Change

Rewrite the guide so the declared-table + vec0 shape is the primary path:

  1. Lead with the [[table]] + vec0 + embed() trigger config (the vector
    template in Docs: path-table vs declared-table tradeoff; FTS5 and vector index templates #960).
  2. Query with WHERE embedding MATCH embed(:q, '') AND k = :n, joined back to
    the base table on rowid, ordered by distance.
  3. Keep the path-table ORDER BY vec_distance_cosine(...) LIMIT k shape as the
    zero-setup option and state the trade explicitly — it is the same
    declared-table-vs-path-table trade Docs: path-table vs declared-table tradeoff; FTS5 and vector index templates #960 documents: no config, always
    current, pays per query; versus config plus --persist, watcher-maintained,
    one embed per query.
  4. Retire or rewrite the ::: tip Top-k is LIMIT k block. It exists to explain
    why MATCH … AND k = does not apply, which stops being true once the
    primary example uses vec0.
  5. Note what the trigger shape inherits from Declared tables: wide-open multi-statement ddl, catalog validation #956: the model id lives in the
    ddl string, so switching models changes the config hash and forces a full
    re-embed. No stale vectors, no ownership tracking.

Depends on #960 for the vector template (or supersedes that half of it).
Related: #956, #994.

Size: S. Docs only.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions