const collectionName = 'Students';
// Query by nested field — no joins needed
domo.post(`/domo/datastores/v2/collections/${collectionName}/documents/query`,
{
'content.wand.core': 'phoenix feather',
}
)
.then((docs) => console.log(docs));
// Count students per house (aggregation)
domo.post(
`/domo/datastores/v2/collections/${collectionName}/documents/query?groupby=content.house&count=count`,
{}
).then(results => console.log(results));[
{
"id": "402778f6-bc8d-4aa5-a581-e08e3fc98c05",
"datastoreId": "daee775a-3be4-410d-ba20-bb0d94ce51cb",
"collectionId": "2148c830-14c2-478f-bb14-5c3019de46b4",
"syncRequired": true,
"owner": "540824222",
"createdBy": "540824222",
"createdOn": "2026-07-31T23:09:34.542Z",
"updatedOn": "2026-07-31T23:16:41.776Z",
"updatedBy": "540824222",
"content": {
"name": "Harry Potter",
"house": "Gryffindor",
"wand": {
"wood": "holly",
"core": "phoenix feather",
"length": 11
},
"courses": [
"Defense Against the Dark Arts",
"Potions",
"Transfiguration"
],
"prefect": false,
"enrolledOn": "1991-09-01",
"lastDetention": "1994-06-08T20:00:00Z"
}
}
]{
"status": 403,
"toe": "2DCMTO3OOK-UZCA0-J004P"
}{
"status": 404,
"statusReason": "DA0088: Invalid collection name: tudents",
"toe": "7AOCDSM8OQ-P1AQ1-UHD0F"
}Query Documents
Query documents using MongoDB query syntax.
Supported operators
All MongoDB query predicates supported in a find() call are available, including comparison, logical, array, data type, bitwise, $expr, $jsonSchema, $regex, $geoWithin, and $geoIntersects. See the MongoDB query predicate documentation for the full operator list.
Unsupported operators
$where— JavaScript evaluation is disabled server-side.$nearand$nearSphere— geospatial proximity searches require an index that AppDB collections do not have.
Examples
The following examples use this sample Students collection:
[
{
"content": {
"name": "Harry Potter", "house": "Gryffindor",
"wand": { "wood": "holly", "core": "phoenix feather", "length": 11 },
"courses": ["Defense Against the Dark Arts", "Potions", "Transfiguration"],
"prefect": false,
"enrolledOn": "1991-09-01",
"lastDetention": "1994-06-08T20:00:00Z"
}
},
{
"content": {
"name": "Hermione Granger", "house": "Gryffindor",
"wand": { "wood": "vine", "core": "dragon heartstring", "length": 10.75 },
"courses": ["Potions", "Transfiguration", "Arithmancy", "Care of Magical Creatures"],
"prefect": true,
"enrolledOn": "1991-09-01",
"lastDetention": "1995-10-15T15:30:00Z"
}
},
{
"content": {
"name": "Ron Weasley", "house": "Gryffindor",
"wand": { "wood": "willow", "core": "unicorn hair", "length": 14 },
"courses": ["Defense Against the Dark Arts", "Potions", "Divination"],
"prefect": true,
"enrolledOn": "1991-09-01",
"lastDetention": "1994-06-08T20:00:00Z"
}
},
{
"content": {
"name": "Draco Malfoy", "house": "Slytherin",
"wand": { "wood": "hawthorn", "core": "unicorn hair", "length": 10 },
"courses": ["Potions", "Transfiguration", "Defense Against the Dark Arts"],
"prefect": true,
"enrolledOn": "1991-09-01",
"lastDetention": "1996-03-12T19:00:00Z"
}
},
{
"content": {
"name": "Luna Lovegood", "house": "Ravenclaw",
"courses": ["Charms", "Defense Against the Dark Arts", "Care of Magical Creatures"],
"enrolledOn": "1992-09-01"
}
}
]
Querying nested fields
AppDB stores documents as arbitrary JSON, so nested objects like wand are queryable directly using dot notation — no joins or schema changes needed. To find all students whose wand core is phoenix feather:
domo.post(`/domo/datastores/v2/collections/Students/documents/query`,
{
'content.wand.core': 'phoenix feather',
}
)
.then((docs) => console.log(docs));
Querying by date
AppDB has two categories of date fields that require different query approaches. Using the wrong approach for a field type fails silently — no error, just incorrect results.
System date fields (createdOn, updatedOn) are stored as BSON DateTime by AppDB. Query them using MongoDB Extended JSON v2 $date syntax:
{"createdOn": {"$gt": {"$date": "2026-01-01"}}}
Content date fields are stored as whatever JSON primitive you write. An ISO 8601 string like "2026-09-01T18:30:00Z" is stored as a BSON String. Two approaches work:
String comparison — ISO 8601 strings sort lexicographically in date order, so standard comparison operators work directly for both date-only (YYYY-MM-DD) and datetime (YYYY-MM-DDTHH:MM:SSZ) strings. To find students who enrolled after the original 1991 cohort:
{"content.enrolledOn": {"$gt": "1991-09-01"}}
To find students with a detention after a specific datetime:
{"content.lastDetention": {"$gt": "1995-01-01T00:00:00Z"}}
$expr + $toDate — converts the string to a date at query time, enabling $date comparisons and handling mixed-precision strings correctly. Works for both date-only and datetime strings:
{
"$expr": {
"$gt": [
{"$toDate": "$content.enrolledOn"},
{"$date": "1992-08-30"}
]
}
}
{
"$expr": {
"$gt": [
{"$toDate": "$content.lastDetention"},
{"$date": "1995-01-01T00:00:00Z"}
]
}
}
Mixing up these approaches produces wrong results without an error.
Using $date against a content string field always returns empty — BSON DateTime never matches BSON String. Using plain string comparison against a system field like createdOn also always returns empty — BSON String never compares against BSON DateTime regardless of the operator used.
To confirm the stored type of any field, use the $type operator. If {"someField": {"$type": "date"}} returns documents, use $date syntax. If {"someField": {"$type": "string"}} returns documents, use string comparison or $expr + $toDate.
Students per house
?groupby=content.house&count=count
Body: {}
[
{"_id": "Slytherin", "count": 1},
{"_id": "Gryffindor", "count": 3},
{"_id": "Ravenclaw", "count": 1}
]
Aggregation query parameters
Field names use dot notation; fields inside content must be prefixed with content. (e.g., content.house). Nested fields like content.wand.length also work. Top-level fields like owner and createdOn can be referenced directly.
Average wand length per house
Because wand is a nested object, content.wand.length works as an aggregation target directly — no joins or flattening needed.
?groupby=content.house&avg=content.wand.length avgWandLength&orderby=avgWandLength descending
Body: {}
[
{"_id": "Gryffindor", "avgWandLength": 11.916666666666666},
{"_id": "Slytherin", "avgWandLength": 10}
]
Course enrollment frequency
unwind produces one document per course value before grouping, so a student enrolled in ["Potions", "Transfiguration"] counts once toward each group.
?unwind=content.courses&groupby=content.courses&count=count&orderby=count descending
Body: {}
[
{"_id": "Potions", "count": 4},
{"_id": "Defense Against the Dark Arts", "count": 4},
{"_id": "Transfiguration", "count": 3},
{"_id": "Care of Magical Creatures", "count": 2},
{"_id": "Divination", "count": 1},
{"_id": "Arithmancy", "count": 1},
{"_id": "Charms", "count": 1}
]
To group by multiple fields, pass a comma-separated list: groupby=content.house,content.prefect. The _id in each result becomes an object — {"_id": {"house": "Gryffindor", "prefect": false}, "count": 1} — instead of a scalar. Aggregation values remain top-level keys using their configured aliases.
const collectionName = 'Students';
// Query by nested field — no joins needed
domo.post(`/domo/datastores/v2/collections/${collectionName}/documents/query`,
{
'content.wand.core': 'phoenix feather',
}
)
.then((docs) => console.log(docs));
// Count students per house (aggregation)
domo.post(
`/domo/datastores/v2/collections/${collectionName}/documents/query?groupby=content.house&count=count`,
{}
).then(results => console.log(results));[
{
"id": "402778f6-bc8d-4aa5-a581-e08e3fc98c05",
"datastoreId": "daee775a-3be4-410d-ba20-bb0d94ce51cb",
"collectionId": "2148c830-14c2-478f-bb14-5c3019de46b4",
"syncRequired": true,
"owner": "540824222",
"createdBy": "540824222",
"createdOn": "2026-07-31T23:09:34.542Z",
"updatedOn": "2026-07-31T23:16:41.776Z",
"updatedBy": "540824222",
"content": {
"name": "Harry Potter",
"house": "Gryffindor",
"wand": {
"wood": "holly",
"core": "phoenix feather",
"length": 11
},
"courses": [
"Defense Against the Dark Arts",
"Potions",
"Transfiguration"
],
"prefect": false,
"enrolledOn": "1991-09-01",
"lastDetention": "1994-06-08T20:00:00Z"
}
}
]{
"status": 403,
"toe": "2DCMTO3OOK-UZCA0-J004P"
}{
"status": 404,
"statusReason": "DA0088: Invalid collection name: tudents",
"toe": "7AOCDSM8OQ-P1AQ1-UHD0F"
}Path Parameters
The name given to the collection in the manifest. Case-sensitive.
Query Parameters
Comma-separated list of properties to group by
Alias for count aggregation
property alias pairs, comma-separated — computes the average of each property. Alias is used as the key in the response.
property alias pairs, comma-separated — computes the minimum of each property.
property alias pairs, comma-separated — computes the maximum of each property.
property alias pairs, comma-separated — computes the sum of each property.
Comma-separated list of properties to unwind (deconstructs an array field, producing one document per element). Must be combined with at least one of count, groupby, avg, min, max, or sum.
Field name or aggregation alias to sort by, followed by ascending or descending. Without aggregation, accepts field names in dot notation; with aggregation, accepts aliases defined by other parameters.
Maximum number of documents to return
Number of documents to skip
Body
MongoDB query object
Response
Array of matching documents
Unique identifier for the Document
Unique identifier of the Datastore that this Document's Collection belongs to.
Unique identifier of the Collection this Document belongs to.
Whether or not this Document needs to be synced by Domo to the associated DataSet; only applies if the syncEnabled option is on for the Collection.
User ID of the Document owner.
User ID of the user who created the Document.
The ISO-8601 timestamp showing when this Document was created.
The ISO-8601 timestamp showing when this Document was last updated.
User ID of the user who last updated the Document.
The actual Document content