Skip to main content
Attach metadata to documents when you add them, then constrain queries to the documents whose metadata matches a filter. Filtering is evaluated on the locally loaded index, so call load_index() (or open a session) before querying with a filter. There is no cloud query.

Attach metadata

Metadata is a map of string keys to string values in every SDK. Convert numbers and dates to strings before you add them. Pass it on each document, whether you add documents to a session, to a new cloud index, or to an existing one.
In Python 1.18.0+, dicts and JSON passed to create_index or add_docs may hold number and boolean metadata values, which are stored as strings. A number such as 30 becomes "30", and a boolean becomes "true" or "false". Filter booleans with those strings, such as {"$eq": "true"}, not with Python True.

Operators

A condition names one field: { field: 'topic', condition: { $eq: 'refund' } }. Compose several with $and / $or (nestable). A single condition can be passed on its own without a wrapper. A condition never matches a document that lacks the field, $ne and $nin included, so a misspelled field name matches nothing and raises no error. Filter values can be strings or numbers; a number is compared in its plain decimal form. A JavaScript Date or a Python datetime is rejected, so convert it first, as in Filter by date.

How ranges compare

$gt, $gte, $lt and $lte compare the stored value with the filter value like this: A plain decimal is one or more digits, optionally preceded by - and optionally followed by . and one or more digits. The digits before the point have no leading zero unless they are just 0. So "0", "-3.5" and "0.25" are plain decimals, while "-", ".5", "5.", "007", "1e3", "+5", " 5" and "NaN" are text, and so is a numeral too large for a 64-bit float.
This rule needs moss >= 1.15.0 (Python), @moss-js/moss >= 1.16.0 (JavaScript), @moss-dev/moss-web >= 1.4.0 (Browser), Elixir moss >= 1.5.0, the Swift SDK
= 0.8.0, or the C SDK >= 0.24.0. Earlier releases order some values differently.

Filter by date

Store dates as Unix epoch seconds in a decimal string, and filter with numbers. Both sides are then plain decimals, so they compare as numbers and in time order. Epoch milliseconds work the same way.
The same filter works on a loaded index: pass it as filter to client.query().
Give Python datetimes a time zone. timestamp() reads a naive datetime as local time.

List every document in a range

A query returns the best matches for its text, and a blank query returns nothing. To list every document in a date range, call get_docs with a filter on a session. It returns every match without ranking, and sort_by orders numbers numerically, so epoch values come back in time order. Python, Swift and C sessions support this; JavaScript and Elixir sessions fetch documents by id only.

ISO 8601 strings

ISO 8601 strings compare as text. Text order is time order only when every value uses one fixed, zero-padded UTC format, such as 2026-01-10T09:00:00Z.
Text ranges are easy to get wrong:
  • Mixed formats break the order. 2026-01-10T09:00:00.5Z sorts before 2026-01-10T09:00:00Z though it is later, and offsets such as +02:00 are not converted to UTC.
  • A date-only upper bound leaves out that day: "2026-01-31T09:00:00Z" sorts after "2026-01-31", so $lte: "2026-01-31" excludes it. Use $lt: "2026-02-01".
  • A text range matches any text that sorts inside it, so a value such as "pending" passes $gt: "2026-01-01".
  • An ISO value never matches an epoch filter, and an epoch value never matches an ISO filter.

Where filters apply

Implementation

Runnable, per-language examples (catalog filters, geo $near, and filtering inside a session) live in the SDK guides: The other SDKs take the same filters:
  • Swift: the typed Filter, such as .and([.greaterThanOrEqual("created_at", 1767225600), .lessThanOrEqual("created_at", 1769903999)]), set as QueryOptions(filter:) or passed to session.getDocs(where:sortBy:). See Graph retrieval.
  • Elixir: the same maps with string keys, such as %{"field" => "created_at", "condition" => %{"$gte" => 1767225600}}, passed as filter:. See Moss.Session.
  • C: the same filter as a JSON string in MossQueryOptions.filter_json. See C API.
  • Browser: the same objects as JavaScript, on a loaded index. See Browser SDK.

Hybrid search

Blend semantic and keyword scoring.

Retrieval

Retrieval strategies overview.