The search API searches the space with its active search backend and exposes SilverBullet’s fuzzy ranker to any Space Lua code.

search.find

search.find(query, options?)

Searches the space with its active search backend. A newer search from the same tab cancels an older one that is still running. Queries shorter than the server's minimum return no results.

Parameters:

  • query (string) — What to search for.
  • options? (table) — mode (one of search.status().capabilities.modes; defaults to the first), scope (pages, meta or all, like the page picker's segments: meta pages are tagged meta, meta/… or template; defaults to all), include/exclude (exact page names; they narrow scope further; without include, pages hidden by a page decoration are left out), limit (maximum pages).

Returns:

  • table — {items, total, partial, notice}. Each item is {page, pos, line, heading, excerpt, highlights}; heading is set when the backend knows it, pos is the match's position in the page, highlights is a list of [start, end] pairs (UTF-16 offsets into excerpt, end exclusive).

Example:

local result = search.find("garden plan", {scope = "pages"})
for _, m in ipairs(result.items) do print(m.page, m.excerpt) end

search.rank

search.rank(objects, phrase, options?)

Fuzzy-ranks objects against a phrase, best match first. The same ranker view panels use for filtering.

Parameters:

  • objects (table) — Objects to rank.
  • phrase (string) — Phrase to match against. An empty phrase returns every object, in the order given.
  • options? (table) — Ranking options. fields maps a field name to its weight, or to { weight, segments = true } to also score the parts of a /-separated value.

Returns:

  • table — The matching objects, best match first.

search.related

search.related(page, options?)

Finds pages related to a page, leaving out pages hidden by a page decoration. Raises an error while search.status().capabilities.related is false (no semantic search, or its index is still building) or when the page isn't in the semantic index yet.

Parameters:

  • page (string) — Page name.
  • options? (table) — limit (maximum number of pages), scope (pages, meta or all, as in search.find; defaults to all). A page outside the scope has no related pages: with scope = "pages", a Meta page gets none.

Returns:

  • table — {items, total, partial, notice}, as search.find returns: the related pages best first, one item per page with its closest passage.

search.status

search.status()

Reports the space's search backend: its name, the query modes it supports (the first is the default), whether it can find related pages, and whether it is ready.

Returns:

  • table — {backend, model, capabilities = {modes, related}, ready, progress, reason}. backend is nil when search is unavailable; reason says why. reason can also carry a warning while ready is true (for example a space with more pages than semantic search is tuned for).

Field weights

options.fields decides what the phrase is matched against, and how much each field counts. A bare number is the weight; { weight, segments = true } additionally scores the parts of a /-separated value, which is what makes pro alp find Projects/Alpha. Per-field scores are combined, so an object matching two weighted fields outranks one matching either alone.

search.rank(objects, "pro alp", {
  fields = {
    name = { weight = 1.0, segments = true },
    aliases = 0.85,
    description = 0.5,
  },
})