query, a session supports deterministic
retrieval — exact lookups that run with no embedding and no similarity
ranking. Use it when you know precisely which documents you want: fetch by id,
filter by metadata, group chunks back into their parent record, and carry a
verbatim structured payload alongside the embedded text.
All of these run on MossSession and are fully local —
no network round trip.
Requires the Moss iOS SDK v0.6.2+ (
.package(url: "https://github.com/usemoss/moss", from: "0.6.2")).Fetch by id (exact, ordered)
getDocs(ids:) returns documents in the exact order requested. Missing ids
are skipped (no error, no gap).
nil returns every document (handy for inspection, expensive on large
indexes); an empty array returns nothing:
Fetch by metadata (typed filter)
getDocs(where:) returns every document matching a metadata predicate — no
query string, no ranking. Build predicates with the typed Filter DSL instead
of hand-written JSON:
sortBy orders results by a metadata field (numeric-aware, so "9" < "50");
ascending defaults to true. Omit sortBy for a deterministic id order.
The Filter DSL
Filter values compose, and FilterValue
is literal-expressible — pass "shoes", 27, 0.7, or false directly:
.and / .or (they nest):
Escape hatch: raw filter JSON
Escape hatch: raw filter JSON
If you already have an engine-format filter string, wrap it with
.raw. Invalid
JSON surfaces as a thrown MossError rather than silently matching everything:Filter works on semantic search too — set
QueryOptions.filter to restrict a query to matching
documents (it takes precedence over the legacy filterJson string):
Group chunks into their parent record
When a logical record (a long document, an article, a transcript) is stored as several sibling chunks that share a parent id,ParentGrouping collapses them
into one result — sibling text assembled in orderField order (numeric-aware),
the best score kept.
GetDocsOptions is the full-control entry point —
ids, filter, sortBy, ascending, and groupByParent in one call.
Grouping also works on semantic query via
QueryOptions.groupByParent, which collapses sibling
hits into one result per record:
For complete records, prefer
getDocs(where:…, groupByParent:) — it groups
over the full matching set. On the semantic query path, grouping over-fetches
candidates and returns topK records, but a record whose siblings fall outside
the fetched window may still be partially assembled. Raise topK if you need
wider coverage there.Verbatim structured payload
Each document can carry an opaquepayload stored and returned unchanged —
never embedded, never searched. It’s the place for the structured record behind
the embedded text (the source row, the full object, anything Codable).
Write it from any Encodable with the structured: initializer:
decodedPayload(_:) returns nil when a document has no payload. The raw string
is also available as DocumentInfo.payload / QueryResult.payload. Indexes
written before a payload was attached load with payload == nil — no migration,
no format break.
Mixing exact and semantic
There’s no blended call — run the two and combine client-side. A common pattern: semanticquery to rank candidates, then getDocs(ids:) to pull the exact,
fully-populated records (with payloads) for the winners: