The data layer accepts standard MongoDB query operators in any place that takes a filter or query document — POST /repository/find/{datatype}, all /dynamic-query/* verbs, audience segments, automation conditions, and rule engine evaluations. This page is the reference.
Field paths point into data. Write data.email, data.address.city, data.tags — never the bare field name.
Comparison
| Field | Type | Description |
|---|---|---|
| $eq | any | Equal. |
| $ne | any | Not equal. |
| $gt | number | string | date | Greater than. |
| $gte | number | string | date | Greater than or equal. |
| $lt | number | string | date | Less than. |
| $lte | number | string | date | Less than or equal. |
Set membership
| Field | Type | Description |
|---|---|---|
| $in | any[] | Field equals one of. |
| $nin | any[] | Field equals none of. |
Existence and type
| Field | Type | Description |
|---|---|---|
| $exists | boolean |
|
| $type | string | number | Match by BSON type — |
Strings
| Field | Type | Description |
|---|---|---|
| $regex | string | Regex match. Pair with |
| $options | string | Regex flags: |
For "starts-with" filters on indexed fields, prefer the keyword-search endpoint (/repository/search/{datatype}) — it uses the search index and is orders of magnitude faster on large collections.
Logical
| Field | Type | Description |
|---|---|---|
| $and | object[] | All clauses must match. Implicit when you list multiple fields at the top level. Use explicit |
| $or | object[] | Any clause matches. |
| $nor | object[] | None of the clauses match. |
| $not | object | Negate the inner expression. |
Arrays
| Field | Type | Description |
|---|---|---|
| $all | any[] | Field array contains all values. |
| $size | number | Array has exact length. |
| $elemMatch | object | At least one array element matches the inner filter as a whole. Use this when filtering arrays of objects: |
Update operators
These appear in the update body of updateOne / updateMany, never in filter.
| Field | Type | Description |
|---|---|---|
| $set | object | Set fields. |
| $unset | object | Remove fields. |
| $inc | object | Increment numeric fields. |
| $push | object | Append to array. |
| $pull | object | Remove matching elements from an array. |
| $addToSet | object |
|
Worked examples
Active leads scored 70+ in the last 30 days
{
"collection": "lead",
"filter": {
"data.status": "active",
"data.score": { "$gte": 70 },
"modifydate": { "$gte": "2026-03-26T00:00:00Z" }
}
}
Customers with at least one tag from a list, no opt-out
{
"collection": "contact",
"filter": {
"data.tags": { "$in": ["promo-q2", "newsletter"] },
"data.optedOut": { "$ne": true }
}
}
Orders that contain a specific SKU at qty >= 2
{
"collection": "order",
"filter": {
"data.lineItems": {
"$elemMatch": { "sku": "MUG-XL", "qty": { "$gte": 2 } }
}
}
}
Products with stock OR explicitly marked as backorderable
{
"collection": "product",
"filter": {
"$or": [
{ "data.stock": { "$gt": 0 } },
{ "data.backorderable": true }
]
}
}
Edge cases
nullvs missing:{ "data.x": null }matches BOTH null values and missing fields. To distinguish, combine with$exists.- Comparing dates: send ISO-8601 strings. The provider parses them when comparing against a
Date-typed field. - Array fields with scalar comparison:
{ "data.tags": "vip" }matches if the array contains"vip". This is convenient but easy to mistake for "equals the literal array". - Nested arrays beyond one level: dot paths stop working once you cross two array boundaries. Use
$elemMatchor an aggregation$unwind. - Case sensitivity: string operators are case-sensitive by default. Use
$regexwith$options: "i", or normalize on write. - Reserved system fields:
pk,sk,version,state,createdate,modifydatelive at the top level of the wrapper, not underdata. Filter them as{ "state": "published" }, not{ "data.state": "published" }.
For the broader query API see Dynamic queries and Repository CRUD.