Nous.Memory.Store.Results (nous v0.17.1)

Copy Markdown View Source

Result post-processing shared by index-plus-entry-table memory stores.

A backend owns its own retrieval — a jaro scan, an inverted index, a vector collection — but they all finish the same way: hydrate the hit ids from an entry table, drop out-of-scope entries, cut below min_score, sort, truncate. This is that tail, and it is public because a Nous.Memory.Store implementation living outside Nous needs exactly the same back half (see Nous.Memory.Store).

Keeping it as one definition is not cosmetic: it was four copies, and the copy that handled scored results was unreachable in three of them, so any scoped vector or full-text search raised BadMapError (see filter_by_scope/2).

Summary

Functions

Every entry in the store's ETS side table, unordered.

Keep only entries whose fields match every key in scope.

Turn a backend's scored hits into the store's {entry, score} result list.

Types

scored()

@type scored() :: {Nous.Memory.Entry.t(), number()}

Functions

all_entries(table)

@spec all_entries(:ets.table()) :: [Nous.Memory.Entry.t()]

Every entry in the store's ETS side table, unordered.

filter_by_scope(entries, scope)

@spec filter_by_scope([Nous.Memory.Entry.t()] | [scored()], map()) ::
  [Nous.Memory.Entry.t()] | [scored()]

Keep only entries whose fields match every key in scope.

Accepts either bare entries or {entry, score} pairs; the shape is dispatched per element, not per list.

This used to be three clauses per store, the last of which handled the scored shape and was unreachable: the clause above it guarded on is_list/1, which a list of {entry, score} pairs also satisfies. Any scoped vector or full-text search therefore reached Map.get/2 with a tuple and raised BadMapError.

rank(hits, table, scope, min_score, limit)

@spec rank(
  [%{id: String.t(), score: number()}],
  :ets.table(),
  map(),
  number(),
  pos_integer()
) :: [
  scored()
]

Turn a backend's scored hits into the store's {entry, score} result list.

hits are %{id: id, score: score} maps from the search backend. Ids with no surviving ETS row are dropped: the index and the side table are written separately, so an id can outlive its entry.