> For the complete documentation index, see [llms.txt](https://docs.contextual.io/documentation-and-resources/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.contextual.io/documentation-and-resources/components-and-data/flows/node-reference/object/query-object.md).

# Query Object

Use a Query Object node in your Flow to query for and return matching Records of the specified Object Type to your Flow.

Unlike the Search Object node which uses search statements and filter operations configured in the node UI, the Query Object node accepts a structured query as JSON, JSONata, or from the `msg` object, giving you full programmatic control over the query sent to the API.

To configure a Query Object node in the [Flow Editor](/documentation-and-resources/components-and-data/flows/node-red-flow-editor.md), drag it from the Palette to the Workspace canvas, then double-click the node to open and configure its behavior.

To configure a Query Object node:

1. Provide an optional **Name** for the node to make your flow easier to read and understand in the Flow Editor UI. If no **Name** is provided, the Flow Editor UI displays the label "Query Objects".
2. Select a **Config** for the node.
3. Select a **Type Id** for the node. Choose from these options:
   * *type* - choose from a dropdown of Display Names for each Object Type in your Contextual tenant. If the dropdown is empty, make sure your Flow has been [initialized with a Config](/documentation-and-resources/components-and-data/flows/node-red-flow-editor/config.md), after which the dropdown will be kept in sync with your tenant.
   * *string* - choose *string* to manually enter the Object Type ID of the Object Type you want to query.
   * *msg.* - choose this option to specify a path in the `msg.` object that contains the Object Type ID value that you want to query against (for example, `msg.payload.thePropertyWithTheObjectTypeId`, `msg.event.thePropertyWithTheObjectTypeId`, or `msg.customObject.thePropertyWithTheObjectTypeId`). The `msg.` object and its contents are available to nodes within any flow in the same Flow Editor window (in other words, across multiple tabs in the Node-RED Flow Editor interface).
   * *flow.* - values in the `flow.` scope can be set and retrieved by nodes that exist within *the same tab* of your flow in the Contextual Flow Editor.
   * *global.* - values in the `global.` scope are shared, and can be set and retrieved, by nodes *across any tab* of your flow in the Contextual Flow Editor.
   * *env variable* - Environmental Variables are a feature of Agents in Contextual. Any Environmental Variables defined as Label/Value pairs for an Agent that is sending events to a Flow are available to the Flow. Type the Label of the Environmental Variable from which you want to use the value.
4. Specify a **Query** to define the criteria for matching Records. For query syntax and examples, see [Query Syntax and Matching Semantics](#query-syntax-and-matching-semantics). The query can be provided as:
   * *JSON* - type or paste a JSON query object directly
   * *JSONata* - use a JSONata expression to dynamically build the query
   * *msg.* - specify a path in the msg object that contains the query, e.g. `msg.payload.myQuery`
5. Specify a required [**Page Size**](#output-format-by-page-size) to limit the number of results that will be returned to your flow per page.
   * The page size can be provided as a *number*, or dynamically via *msg.*, *flow.*, *global.*, or *env variable* paths.
   * When the page size is set to `1`, the output will contain the single matching record directly rather than a result set wrapper. If no records match, the output will be `undefined`. This differs from the behavior at page sizes of `2` or greater, where zero matches return an envelope with an empty `items` array (`{items: []}`).
6. Optionally enable **Include Total** to include a `totalCount` in the response indicating the total number of matching Records across all pages.
7. Add optional **Order By** statements by clicking **"+add"** at the bottom of the Order By panel to order the results using the value of a property. (On the node's JSON configuration, `order` is an array of JSON objects: `{name: "<property>", direction: "asc" | "desc"}`. Both fields are required.)
   * Type the property name on the left
   * Designate either `asc` or `desc` sort order on the right.
8. Add optional **Fields** statements by clicking **"+add"** at the bottom of the Fields panel to limit which properties are returned in the results. (On the node configuration, `fields` is an array of JSON objects: `{name: "<property>"}`. Plain strings are not accepted.)
   * Type the property name to include
   * Returned records will contain only the listed fields, plus [`_metaData`](/documentation-and-resources/components-and-data/object-types/object-type-details/data-schema/automatic-metadata.md) which is always included regardless of the fields list.
9. Set the **Output** [`msg.` object path](/documentation-and-resources/components-and-data/flows/message-object.md) for the query results (for example, `msg.payload`).
10. Set the **Response** `msg.` object path for HTTP response metadata, including status code and headers. For example, `msg._response`.

## Query Syntax and Matching Semantics

A query is a JSON object that describes the set of conditions a record must satisfy to be included in the output. Each condition in a query maps a field path to a match value or match operator.

A field path may reference a top-level field or nested properties. Every field path in a query must include a `$.` prefix. Use dot notation after the prefix (for example, `$.vendor.address.city`).

Field paths may traverse arrays automatically. If any field in the path is an array, the condition is met when any array item matches.

### Empty Queries

An empty query matches all records:

```json
{}
```

### Equality Checks

Pairing a field or field path with a plain value performs an equality check. For example, this query matches records whose `status` equals `"APPROVED"`:

```json
{
   "$.status": "APPROVED"
}
```

### Multiple Top-Level Conditions

Multiple top level conditions use AND. For example, this only matches records where both conditions are true:

```json
{
  "$.status": "open",
  "$.priority": "high"
}
```

### Implicit Array Matching

If the value at a path is an array, the condition is tested against each element in the array. A match on any element counts as a match on the record.

For example, this query matches a record with `"b"` in a `letters` array (`{ "letters": ["a", "b", "c"] }`):

```json
{
   "$.letters": "b"
}
```

### Multiple Conditions on the Same Array

When multiple conditions target the same array, each condition is evaluated independently across all elements in the array. A record matches if *any* element meets the first condition and *any* element meets the second condition, but they don't have to be the same element.

When all conditions must apply to the same array element, use `$elemMatch`. For example, this query:

```json
{
   "$.items": {
      "$elemMatch": {
         "sku": "shirt",
         "tags": "blue"
      }
   }
}
```

matches *only* records where one item has both `sku: "shirt"` and a `tags` value of `"blue"`:

```json
{
  "items": [
    { "sku": "shirt", "tags": ["blue", "large"] }
  ]
}
```

### Supported Query Operators

Supported operators include:

* `$all`: match records where an array field contains all provided values
* `$and`: match records satisfying all conditions
* `$elemMatch`: match records where an array field contains an element satisfying a sub-condition
* `$exists`: match records where a field is present (or absent when set to `false`)
* `$gt`: match records where a field is greater than a value
* `$gte`: match records where a field is greater than or equal to a value
* `$in`: match records where a field value equals any value in the provided array
* `$lt`: match records where a field is less than a value
* `$lte`: match records where a field is less than or equal to a value
* `$nin`: match records where a field value is not in the provided array
* `$not`: invert a query predicate
* `$or`: match records satisfying at least one condition
* `$regex`: match records where a field value matches a regular expression

### JSONata Integration

You can generate queries dynamically using [JSONata](https://jsonata.org/). When you do, the `$.` prefix is preserved in the output:

```jsonata
{
  "$.tags": {
    "$in": [tags.(name)]
  },
  "$.vendor.id": vendor.id,
  "$.status": "APPROVED",
  "$.isPaid": false
}
```

### Examples

{% tabs %}
{% tab title="Filter by Tag or Category" %}

```json
{
  "$or": [
    { "$.tags": { "$in": ["urgent"] } },
    { "$.category": "utilities" }
  ]
}
```

{% endtab %}

{% tab title="Nested Field and Range Queries" %}

```json
{
  "$.vendor.id": "vendor-123",
  "$.amount.total": { "$gt": 0 },
  "$.dueDate": { "$lte": "2026-06-30" }
}
```

{% endtab %}
{% endtabs %}

## Output Format by Page Size

The Query Object node writes its results to the **Output** `msg.` path (for example, `msg.payload`). The format of that output depends on the configured page size and whether any records match the query.

| Page Size | Matches     | Output                               |
| --------- | ----------- | ------------------------------------ |
| `>= 2`    | One or more | `{items: [<record>, <record>, ...]}` |
| `>= 2`    | Zero        | `{items: []}`                        |
| `1`       | One         | `<record>`                           |
| `1`       | Zero        | `undefined`                          |

A `<record>` is a JSON object whose properties are determined by the Object Type's data schema, plus [`_metaData`](/documentation-and-resources/components-and-data/object-types/object-type-details/data-schema/automatic-metadata.md) which the platform always includes.

When **Include Total** is enabled, the output includes a top-level `totalCount` property indicating the total number of matching records across all pages. When more pages of results exist, the output includes a top-level `nextPageToken` property. `nextPageToken` can be used with `msg.pageToken` to retrieve subsequent pages.

```json
{
   "items":[
      {...},
      {...}
   ],
   "nextPageToken":"<token>",
   "totalCount":15
}
```

{% hint style="info" %}
When page size is set to 1 on a query node, the output only includes the top-level item, never an object with an `items` array. Additionally, the output never includes a `totalCount` or `nextPageToken` property, even if **Include Total** is enabled.
{% endhint %}

## Source Tab

**Unfold all pages to source** — when this checkbox is enabled, the node automatically paginates through all result pages rather than returning a single page. Results are produced as a source stream, with each record emitted as an individual message. The node's label in the Flow Editor changes to include a `[Source]` prefix. When this is enabled, the [default output format](#output-format-by-page-size) does not apply — each message carries a single record on the **Output** `msg.` path, regardless of page size.

**Parallelism** — visible when **Unfold all pages to source** is not enabled. When this node receives a source stream from an upstream node, these settings control how many records the node processes concurrently:

* *None* — processes records sequentially
* *Ordered* — processes up to **Max** records concurrently while preserving output order
* *Unordered* — processes up to **Max** records concurrently and emits results as they finish

These settings only apply when the node appears within a stream (in other words, after a Source From node in a flow).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.contextual.io/documentation-and-resources/components-and-data/flows/node-reference/object/query-object.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
