MongoDB uses a multi-stage pipeline model where documents flow through an ordered sequence of transformation stages. DQL uses a single declarativeDocumentation Index
Fetch the complete documentation index at: https://docs.ditto.live/llms.txt
Use this file to discover all available pages before exploring further.
SELECT statement where filtering, projection, grouping, sorting, and limiting are all expressed at once. There are no stages to compose — the query optimizer decides execution order.
This means most MongoDB aggregations collapse to a single DQL SELECT. Operations with no DQL equivalent — joins, window functions, set algebra, advanced math, and several array accumulators — are noted as gaps throughout and collected in the Known Gaps section.
AI Agent Prompt
Use this prompt with any AI coding assistant to convert a MongoDB aggregation pipeline to DQL.Copy AI Agent Prompt (Click to Expand)
Copy AI Agent Prompt (Click to Expand)
Quick Reference
The table below covers the most common MongoDB aggregation pipeline stages and expression operators. Where a direct equivalent exists, a DQL example is provided. Where one doesn’t exist yet, the notes column says so — if any of those are important to your use case, reach out to support and let us know.| MongoDB | DQL Equivalent | Notes |
|---|---|---|
$match | WHERE | Full operator parity: =, !=, <, >, BETWEEN, IN, LIKE, IS NULL, IS MISSING, etc. |
$project (include fields) | SELECT field1, field2 | Direct equivalent |
$project (exclude fields) | SELECT products.*, MISSING field1 FROM products | Wildcard must be qualified — SELECT *, MISSING field1 is a syntax error |
$project (computed fields) | SELECT expr AS alias | Full expression support |
$addFields / $set | SELECT products.*, expr AS new_field FROM products | Same pattern — qualified wildcard plus computed fields |
$unset (top-level) | SELECT products.*, MISSING field FROM products | Same as exclude projection |
$unset (nested field) | object_unset(obj, 'field') | Use in SELECT projection for nested exclusion |
$group | GROUP BY | Works with COUNT, SUM, AVG, MIN, MAX, MEDIAN |
$group with $push | — | No direct equivalent. No array-accumulating aggregate. |
$group with $addToSet | COUNT(DISTINCT ...) | Counts distinct values only; no array-building equivalent |
$group with $first / $last | — | No direct equivalent. |
$group with $stdDevPop / $stdDevSamp | — | No direct equivalent. |
$group with $percentile | — | No direct equivalent. |
$accumulator / $function | — | No direct equivalent. |
$sort | ORDER BY ... [ASC|DESC] | Direct equivalent |
$limit | LIMIT n | Direct equivalent |
$skip | OFFSET n | Direct equivalent |
$count | SELECT COUNT(*) | Direct equivalent |
$unwind | ARRAY ... FOR ... IN ... END / ANY ... IN ... SATISFIES | No row-multiplying unwind. Use array transform or search expressions. |
$lookup | — | Use a transaction to query multiple collections at a consistent snapshot — see example. |
$facet | Multiple separate queries | Use a read-only transaction to run multiple aggregations against the same snapshot — see example. |
$bucket / $bucketAuto | CASE WHEN ... END + GROUP BY | Manual bucketing via CASE expressions |
$replaceRoot / $replaceWith | — | No direct equivalent. |
$merge / $out | — | Use a transaction for atomic read-modify-write — see example. |
$sample | — | No random document sampling. |
$unionWith | — | No collection union. |
$geoNear | — | No geospatial support. |
$densify / $fill | — | No time-series gap filling. |
$redact | — | No document-level access control. |
$setWindowFields | — | No window functions. |
$cond | CASE WHEN ... THEN ... ELSE ... END | Direct equivalent; DQL CASE is more expressive |
$ifNull | ifnull(v1, v2, ...) / coalesce(...) | Direct equivalent |
$switch | Simple or searched CASE | Direct equivalent |
$map | ARRAY expr FOR v IN source END | SDK v5+ |
$filter | ARRAY v FOR v IN source WHEN condition END | SDK v5+ |
$reduce | — | No direct equivalent. |
$arrayElemAt | array[index] | Direct subscript access |
$size (array) | array_length(arr) | Direct equivalent |
$in (array membership) | array_contains(arr, val) | Direct equivalent |
$concatArrays | — | No documented direct equivalent. |
$slice | — | No documented direct equivalent. |
$reverseArray | — | No array reversal function. |
$sortArray | — | No in-expression array sort. |
$zip | — | No array zip. |
$setUnion / $setIntersection / $setDifference | — | No set algebra operators on arrays. |
$mergeObjects | object_concat(obj1, obj2, ...) | Direct equivalent |
$objectToArray | object_content(obj, 'fields') | Available in SDK v4.11+ |
$arrayToObject | OBJECT name_expr:value_expr FOR ... IN ... END | Object transformation expression, SDK v5+ |
$dateFromString | date_cast(str, format) | Direct equivalent |
$dateToString | date_format(date, format) | Direct equivalent |
$dateAdd / $dateSubtract | date_add(...) / date_sub(...) | Direct equivalent |
$dateDiff | date_diff(date1, date2, part) | Direct equivalent |
$year, $month, $day, etc. | date_part(date, 'year') | Unified single function |
$regexMatch | regexp_like(...), LIKE, ILIKE, SIMILAR TO | Multiple pattern-matching options |
$substr / $substrCP | substr(str, start, len) | Direct equivalent |
$concat | concat(...) or || operator | Direct equivalent |
$toLower / $toUpper | lower(str) / upper(str) | Direct equivalent |
$trim / $ltrim / $rtrim | `trim`(str) / ltrim() / rtrim() | Direct equivalent; trim requires backtick quoting |
$type | type(x) / json_type(x) | Direct equivalent |
$toString, $toInt, etc. | cast(v, 'string') / CAST(v AS type) | Unified cast function |
$abs | abs(x) | Direct equivalent |
$ceil | ceil(x) | Direct equivalent |
$floor | floor(x) | Direct equivalent |
$round / $trunc | — | No rounding or truncation functions. |
$sqrt / $pow / $exp / $ln / $log | — | No advanced math functions. |
$sin, $cos, $tan, etc. | — | No trigonometric functions. |
| Pipeline composition (multi-stage) | Single declarative SELECT | Mental model shift, not a feature gap |
Filtering
$match → WHERE
MongoDB
DQL
=, !=, <, >, <=, >=, BETWEEN, IN, NOT IN, LIKE, ILIKE, SIMILAR TO, IS NULL, IS NOT NULL, IS MISSING, IS NOT MISSING.
DQL
Projection
$project (include fields)
MongoDB
DQL
$project (computed fields)
MongoDB
DQL
$addFields / $set — add fields while keeping all existing ones
MongoDB
DQL
SELECT *, price * 1.1 AS adjusted_price FROM products is a syntax error. The wildcard must be qualified with the collection name: SELECT products.*, ....$project (exclude fields) / $unset
MongoDB
DQL
MISSING override the wildcard expansion — products.* includes the field, but the explicit MISSING projection wins and the key is absent from output.
For excluding a nested field within an object value, use object_unset:
DQL
Grouping and Aggregation
$group
MongoDB
DQL
COUNT, SUM, AVG, MIN, MAX, MEDIAN, MID.
HAVING — filter on aggregated results
MongoDB
DQL
$addToSet / COUNT(DISTINCT ...)
DQL supports COUNT(DISTINCT ...) for counting unique values but does not accumulate values into an array within a group:
DQL
Sorting, Limiting, and Pagination
$sort, $limit, $skip
MongoDB
DQL
Counting
$count
MongoDB
DQL
DQL
Array Operations
$unwind → array transform or search expression
MongoDB’s $unwind duplicates a document for each array element. DQL has no row-multiplying unwind. Instead:
- Transform array contents in-place with the
ARRAYexpression - Filter documents based on array contents with
ANY ... IN ... SATISFIES
MongoDB
DQL
DQL
$map → ARRAY transformation expression
MongoDB
DQL
$filter → ARRAY ... WHEN expression
MongoDB
DQL
$arrayElemAt → subscript operator
MongoDB
DQL
$size → array_length()
MongoDB
DQL
$in (array membership) → array_contains()
MongoDB
DQL
Object Operations
$mergeObjects → object_concat()
MongoDB
DQL
$objectToArray → object_content()
MongoDB
DQL
object_content() returns an array of single-key objects. Available in SDK v4.11+. See Object Operators for full configuration options.
$arrayToObject → OBJECT transformation expression
MongoDB
DQL
Conditional Expressions
$cond → CASE WHEN
MongoDB
DQL
DQL
$ifNull → ifnull() / coalesce()
MongoDB
DQL
coalesce(v1, v2, ...) is a synonym that returns the first non-null, non-missing value.
$switch → simple CASE
MongoDB
DQL
Bucketing
$bucket / $bucketAuto → CASE + GROUP BY
MongoDB
DQL
Date Functions
| MongoDB | DQL | Notes |
|---|---|---|
$dateFromString | date_cast(str, format) | Converts string to epoch milliseconds |
$dateToString | date_format(date, format) | Converts epoch ms to formatted string |
$dateAdd | date_add(date, part, count) | Parts: year, mon, day, hour, min, sec, ms |
$dateSubtract | date_sub(date, part, count) | Negative count on date_add is equivalent |
$dateDiff | date_diff(date1, date2, part) | Returns integer count of parts between dates |
$year / $month / $day / etc. | date_part(date, 'year') | Single function; parts: year, mon, day, hour, min, sec, weekday, monthname |
$dateTrunc | date_trunc(date, part) | Truncates to the given part |
DQL
String Functions
| MongoDB | DQL | Notes |
|---|---|---|
$regexMatch | regexp_like(str, pattern[, flags]) | Also: LIKE, ILIKE, SIMILAR TO |
$regexFind | regexp_like(...) | Match test only; no capture group extraction |
$substr / $substrCP | substr(str, start[, len]) | Zero-based index |
$concat | concat(str, ...) or str1 || str2 | Direct equivalent |
$toLower | lower(str) | Direct equivalent |
$toUpper | upper(str) | Direct equivalent |
$trim | `trim`(str) | Backtick quoting required; ltrim, rtrim also available |
$ltrim | ltrim(str[, chars]) | Direct equivalent |
$rtrim | rtrim(str[, chars]) | Direct equivalent |
$indexOfCP | pos(str, substr) | Returns zero-based index; -1 if not found |
$strLenCP | char_length(str) | Direct equivalent |
$strLenBytes | byte_length(str) | Direct equivalent |
$split | split(str, delim) | Returns array of parts |
$replaceOne / $replaceAll | — | No string replace function. |
DQL
Type Inspection and Casting
$type → type() / json_type()
MongoDB
DQL
type() returns DQL type names (boolean, string, integer, float, object, array, binary, null, missing). json_type() returns JSON type names (boolean, string, number, object, array, binary, null), returning "null" for MISSING values.
$toString, $toInt, $toDouble, etc. → cast()
MongoDB
DQL
'string', 'integer', 'float', 'boolean', 'binary'. Also accepts CAST(v AS type) SQL syntax. Returns MISSING if conversion is not possible.
Multi-Stage Pipelines → Single SELECT
A MongoDB pipeline composing multiple stages maps to a single DQLSELECT:
MongoDB
DQL
Transaction Workarounds
Ditto’stransaction() API runs multiple DQL statements in a single atomic block at serializable isolation — either all statements commit or none do. This covers several patterns that have no direct DQL equivalent. Examples below use JavaScript; the same pattern applies in all supported SDKs.
Simulating Joins
DQL has no join syntax, but a read-only transaction guarantees both queries see the same consistent snapshot of the store. Combine the results in application code:JavaScript
Consistent Multi-Query Snapshot
The equivalent of$facet — run independent aggregations that are guaranteed to reflect the same point in time:
JavaScript
Atomic Read-Modify-Write
The equivalent of$merge / $out — aggregate, transform in application code, then write the results back in the same atomic operation:
JavaScript
Known Gaps
The following MongoDB aggregation capabilities have no DQL equivalent.Pipeline Stages
| MongoDB | Workaround |
|---|---|
$lookup | No joins. Use a transaction to query multiple collections at a consistent snapshot and join in application code. |
$graphLookup | No graph traversal. Implement multi-hop lookups in application code. |
$unionWith | No collection union. Run separate queries and merge results in application code. |
$unwind (row multiplication) | No row-multiplying unwind. Use ARRAY transform or ANY/EVERY search expressions for in-place operations. |
$facet | No single-query equivalent. Use a read-only transaction to run multiple aggregations against a consistent snapshot. |
$replaceRoot / $replaceWith | No direct equivalent. Restructure data at insert time, or select nested fields explicitly. |
$merge / $out | Queries are read-only. Use a transaction to aggregate, transform, and write back atomically. |
$sample | No random sampling. Fetch a larger result set and sample in application code. |
$setWindowFields | No window functions ($rank, $denseRank, $expMovingAvg, etc.). |
$densify / $fill | No time-series gap filling or null-value backfill. |
$geoNear | No geospatial support. |
$redact | No document-level access control expressions. |
Grouping and Accumulators
| MongoDB | Workaround |
|---|---|
$push / $addToSet (array accumulator) | No array-building aggregate. Collect values in application code after querying. |
$first / $last / $firstN / $lastN | No ordered first/last value within a group. Use a subquery approach or handle in application code. |
$top / $topN / $bottom / $bottomN | No top-N per group. Sort and limit in application code. |
$stdDevPop / $stdDevSamp | No standard deviation aggregates. |
$percentile | No percentile aggregate. |
$accumulator / $function | No user-defined aggregate or expression functions. |
Array Operations
| MongoDB | Workaround |
|---|---|
$reduce | No fold/reduce expression. Implement in application code. |
$concatArrays | No array concatenation expression. Combine in application code. |
$slice | Use subscript array[index] for single elements; slice in application code. |
$reverseArray | No array reversal. Reverse in application code. |
$sortArray | No in-expression array sort. Sort in application code. |
$zip | No array zip. Implement in application code. |
$setUnion / $setIntersection / $setDifference / $setEquals / $setIsSubset | No set algebra on arrays. Implement using ARRAY transforms and ANY/EVERY expressions. |
String Operations
| MongoDB | Workaround |
|---|---|
$replaceOne / $replaceAll | No string replace function. Use regexp_like to match; replace in application code. |
Math Functions
DQL providesabs(), ceil(), and floor(). The following have no equivalent:
| MongoDB | Workaround |
|---|---|
$round / $trunc | Use floor(x + 0.5) to approximate rounding; truncate in application code. |
$sqrt | No square root. Compute in application code. |
$pow | No exponentiation. Compute in application code. |
$exp / $ln / $log / $log10 | No exponential or logarithm functions. Compute in application code. |
$sin, $cos, $tan, $asin, $acos, $atan, $atan2, etc. | No trigonometric functions. Compute in application code. |
$degreesToRadians / $radiansToDegrees | No angle conversion functions. |