Type identifier:
object:queryCategory: Object Operations
Queries the Records of a Schema that match a filter, with pagination and ordering. Returns the matching Records with their metadata, or, with a select/groupBy shape, rows of chosen fields, aggregates over relationships, and grouped counts and totals. Use this node to retrieve data for processing, display, or downstream operations.
Handle | Data Type | Required | Description |
|---|---|---|---|
| Varies | Varies | Dynamic handles for filter variables |
Input handles are dynamically generated based on the variables configuration:
id propertyrequired propertyHandle | Data Type | Description |
|---|---|---|
|
| Query results (single or array) |
resultsfirstOnly) or Array (if multiple)select or groupBy: one row per Record (or per group), keyed by the select entries' output names, typed from the shape. See Selecting fields, aggregates and groups.Includes (without select or groupBy):
id: Record IDschemaId: Schema IDcreatedAt: Creation timestampupdatedAt: Last update timestampcreatedById: Creator IDupdatedById: Last updater IDNotes:
null if firstOnly and no resultsProperty | Type | Required | Default | Description |
|---|---|---|---|---|
|
| Yes |
| Display label for the node |
|
| Yes |
| CUID2 of the Schema to query |
|
| No |
| Variable definitions for filtering |
|
| No |
| Filter criteria |
|
| No |
| Return single Record vs array |
|
| No |
| Maximum Records to return (capped at |
|
| No |
| Skip N Records |
|
| No |
| Sort order |
|
| No |
| Property to sort by |
|
| No |
| The output shape: fields, aggregates and group keys. See Selecting fields, aggregates and groups |
|
| No |
| Groups the Records: one result row per group |
variablesNotes:
spaceIdentityId always availablefiltereq, ne, gt, gte, lt, lte, contains, startsWith, endsWith, in, notIn, isNull, isNotNullNotes:
limitnumber2501000 (hard cap)Notes:
[0, 1000]. A configured limit of 5000 is silently reduced to 1000; a negative value is clamped to 0.firstOnly is true, the effective limit is 1 regardless of the configured value.Without select or groupBy, the node returns whole Records. Set select (and optionally groupBy) to return rows of a chosen shape instead. The shape is the same as the select and groupBy of Record Queries, with the same rules. For how it works, see The Record Query Shape.
select is an ordered list of entries. Each result row has one key per entry, its output name (alias), in select order:
{ "kind": "field", "id", "path", "alias"? }, or a path string as shorthand) returns a property or a standard property (id, createdAt, …);{ "kind": "aggregate", "id", "alias", "fn", "path"?, "filter"?, "over"? }) returns count, sum, avg, min or max. With over: { "relationshipId", "direction" } it aggregates the Records linked to each returned Record through that relationship (a rollup); direction is the side of the relationship the aggregated Records are on. filter limits the aggregated Records (for example, a count of only the released items). An aggregate filter takes literal values only: it cannot use the node's variables or spaceIdentityId;{ "kind": "group", "id", "groupBy", "alias"? }, or the group key's alias as shorthand) returns a key of each group.groupBy (up to 4 keys) makes the query grouped: each row is one group of the Records matching filter. A key groups by a string, number, boolean, date or duration property (or createdAt, updatedAt, createdById, updatedById), or, with over, by the Records linked through a relationship; bucket (day, week, month, quarter, year) groups a date by calendar period. A grouped query selects only group keys and aggregates without over, which aggregate each group's Records.How the node's other settings apply to a shaped query:
Setting | With |
|---|---|
| Selects the Records (before grouping). Variables are populated as usual. |
| Sorts the rows. Defaults to |
| Default |
| Skips rows (or groups). |
| Returns the first row, or |
The results output is typed from the shape: each field has its property's type, a count is a number, a sum/avg has the type of the number or duration it reads, and min/max the type of the property it reads. Values may be null (an unset field, an aggregate with nothing to aggregate, the group of unset values). Changing the shape changes the output type: existing edges stay connected and downstream nodes take the new type, but an edge is only type-checked when it is connected, so check the nodes that read results after changing the shape.
Like a whole-Record query, a shaped query runs with the Space's authority, not as the user who started the run: role filters do not apply, and relationship aggregates count every live linked Record. Only the queried Schema's Space is read: a relationship must link two live Schemas of that Space. Removed Records and removed links are never counted.
In Studio, choose Selected fields, aggregates and groups under Output in the node's details, then add group keys, fields, aggregates and records columns in the Output window (reopen it with Edit output). A records column lists the first linked Records of each row, or the first Records of each group, with the fields, sort and limit you choose. Aggregates over a relationship pick the relationship by its name on the queried Schema; Only include records where… sets an aggregate's filter.
The number of items in each release, and how many of them are released:
{
"type": "object:query",
"data": {
"label": "Release item counts",
"schemaId": "release-schema-id",
"orderBy": "title",
"order": "asc",
"select": [
"title",
{
"kind": "aggregate",
"id": "items",
"alias": "items",
"fn": "count",
"over": { "relationshipId": "in-release-relationship-id", "direction": "from" }
},
{
"kind": "aggregate",
"id": "released",
"alias": "released",
"fn": "count",
"over": { "relationshipId": "in-release-relationship-id", "direction": "from" },
"filter": { "type": "property", "path": "status", "operator": "eq", "value": "released" }
}
]
}
}The relationship links Items (from) to Releases (to), so the aggregated Items are on the from side. results:
[
{ "title": "R1", "items": 3, "released": 2 },
{ "title": "R2", "items": 0, "released": 0 }
]{
"type": "object:query",
"data": {
"label": "Items per status",
"schemaId": "item-schema-id",
"groupBy": [{ "id": "status", "path": "status" }],
"select": ["status", { "kind": "aggregate", "id": "count", "alias": "count", "fn": "count" }]
}
}results: [{ "status": "draft", "count": 2 }, { "status": "released", "count": 5 }].
{
"type": "object:query",
"data": {
"label": "Items per month",
"schemaId": "item-schema-id",
"orderBy": "createdAt",
"order": "desc",
"groupBy": [{ "id": "month", "alias": "month", "path": "createdAt", "bucket": "month" }],
"select": [
"month",
{ "kind": "aggregate", "id": "count", "alias": "count", "fn": "count" },
{ "kind": "aggregate", "id": "points", "alias": "points", "fn": "sum", "path": "points" }
]
}
}results: [{ "month": "2026-02-01", "count": 4, "points": 21 }, { "month": "2026-01-01", "count": 3, "points": 8 }]. A month is the date of its first day; a date-time is placed in a month in the run's timezone (the timezone preference of the user who started it), or UTC.
A shaped query aggregates on the server, over every matching Record, without loading them into the run. List - Aggregate is the node for aggregating a list the run already holds, such as the output of another node or an HTTP response.
A shape that a Record query rejects (an unknown property, a field in a grouped query, a relationship of another Schema, a limit over the limits above) fails the node with INVALID_QUERY and the reason. A filter that cannot be evaluated matches nothing, as in a Record query, rather than failing with INVALID_FILTER.
The Object - Query node enforces a hard cap on the number of Records a single run can return.
Setting | Value | Notes |
|---|---|---|
Default |
| Applied when |
Minimum |
| Negative values are clamped to |
Maximum |
| Configured values above |
|
| Overrides the configured |
For result sets larger than ~1000 Records, a single run of the Object - Query node will not return them all. See the patterns below.
The Object - Query node supports offset + limit pagination. Both are configured directly on the node.
Behaviour | Detail |
|---|---|
First page |
|
Subsequent pages |
|
End-of-results detection | When the returned |
Stable ordering | Without a stable sort, |
Concurrent writes |
|
Cursor-based pagination tokens | Not supported. The node does not emit a |
offset + limitEach iteration advances offset by limit; a page with fewer than limit results is the last page.
{
"type": "object:query",
"data": {
"label": "Page through orders",
"schemaId": "order-schema-uuid",
"variables": [{ "id": "pageOffset", "type": { "type": "number", "required": true } }],
"orderBy": "createdAt",
"order": "asc",
"limit": 1000,
"offset": 0
}
}The pageOffset variable supplies offset from the surrounding Flow. A page with fewer than limit results is the last page (see Pagination).
Selective filters (properties, time windows, status) can reduce the candidate set so that it fits within 1000 Records.
{
"type": "object:query",
"data": {
"label": "Yesterday's failed orders",
"schemaId": "order-schema-uuid",
"filter": {
"type": "and",
"filters": [
{
"path": "status",
"type": "property",
"value": { "type": "literal", "value": "failed" },
"operator": "eq"
},
{
"path": "createdAt",
"type": "property",
"value": { "type": "contextValue", "valueId": "sinceTimestamp" },
"operator": "gte"
}
]
},
"orderBy": "createdAt",
"order": "desc",
"limit": 500
}
}When the goal is a count, sum, or other reduction rather than the rows themselves, use a groupBy shape for counts and totals per group, or an aggregate over a relationship for each Record's related Records: the server aggregates every matching Record, however many there are. List - Aggregate remains the node for aggregating a list already in the run.
Scenario | Behaviour |
|---|---|
Schema not found | The run fails with error code |
Invalid filter | The run fails with error code |
Invalid | The run fails with error code |
No results | Returns |
{
"type": "object:query",
"data": {
"label": "Get User by ID",
"schemaId": "user-schema-uuid",
"variables": [
{
"id": "userId",
"type": { "name": "userId", "type": "string", "required": true }
}
],
"filter": {
"path": "id",
"type": "property",
"value": { "type": "contextValue", "valueId": "userId" },
"operator": "eq"
},
"firstOnly": true
}
}{
"type": "object:query",
"data": {
"label": "List Recent Orders",
"schemaId": "order-schema-uuid",
"filter": {
"path": "status",
"type": "property",
"value": { "type": "literal", "value": "completed" },
"operator": "eq"
},
"orderBy": "createdAt",
"order": "desc",
"limit": 10,
"offset": 0
}
}{
"type": "object:query",
"data": {
"label": "Search Products",
"schemaId": "product-schema-uuid",
"variables": [
{ "id": "minPrice", "type": { "type": "number" } },
{ "id": "category", "type": { "type": "string" } }
],
"filter": {
"type": "and",
"filters": [
{
"path": "price",
"type": "property",
"value": { "type": "contextValue", "valueId": "minPrice" },
"operator": "gte"
},
{
"path": "category",
"type": "property",
"value": { "type": "contextValue", "valueId": "category" },
"operator": "eq"
},
{
"path": "active",
"type": "property",
"value": { "type": "literal", "value": true },
"operator": "eq"
}
]
},
"limit": 50
}
}