Stage operators overview

cMQL supports all aggregation stages [see the API]
Bellow are only some of them

match

:age is a field reference ,will become "$age"

(q :testdb.testcoll
(>_ :age 20)
(=_ :gender "male"))

*Both will become one match stage with $and and $expr

project

Project with addFields []

(q :testdb.testcoll
[:!_id :name :age {:blond (= :hairColor "blond")}])

Project of MQL has a "weird" behaviour,when we add new field,that exists
Replaces always except

  • array-> add document => array with all members that document

If you want to replace an array field with a document field use this notation (! is like remove the field,first and then add it)

{:!myfield adocument}

Something else important is the use of literal when added new fields with number values

{:myfield (literal 2)} ;;if only 2 it will not add field,just keep the :myfield if it exists

addFields

AddFields {}

(q :testdb.testcoll
{:maleStudent (and (= :gender "male") (= :type "student"))
:femaleStudent (and (= :gender "female") (= :type "student"))})

AddFields of MQL has a "weird" behaviour,when we add new field,that exists

Replace always except

  • array-> add document => array with all members that document
  • document-> add document => merge documents

If you want to replace even if you do the above 2 use the !

{:!myfield adocument}

lookup

Lookup,merge when equal on the join field

(lookip :a :acoll.e :ajoined) ; join if :a value == :e value on ajoined field

Lookup with pipeline to allow more join creteria(not just equality on 2 field) also the pipeline allows the joined doc to have any shape (not just merge) :ajoined will be an array with the result of the pipeline

(lookup-p :coll2
[:v1- :afield ...] ; optional
[stage1
stage2]
:ajoined)

Join

This is exactly like SQL join Internally is $lookup $unwind and $replaceRoot

(q :testdb.testcoll
(join :songs.songid)) ; assumes join on songid
(q :testdb.testcoll
(join :songn :songs.songid)) ; join if songn==songid

group

In this grouping :_id will be renamed to :songid

(group :songid
{
:points (sum- :points)
:views (sum- :views)
:dates (conj- :date)
})

merge

(merge :mydb.mycoll)
(merge :mydb.mycoll ;;no variables used
(if-match [field1 fied2] ;;becomes :on [field1 field2]
whenMatched ;;can also be pipeline
whenNoMatched))
(merge :mydb.mycoll
(if-match [field1 fied2]
(let- [:v1- :f1 :v2- :f2 ...] ; to refer pipeline doc fields
whenMatched ;;can also be pipeline
whenNoMatced)))
whenMatched
replace (keep pipelines)
keepExisting (keep collections)
merge (merge old+new document ,like mergeObjects)
fail (stops in the middle if happen,no rollback)
pipeline(used like update pipepline =>,i can use only
$addFields=$set $project=$unset $replaceRoot=$replaceWith)
whenNotMatched
insert (insert pipelines)
discard (ignore pipelines)
fail (if pipeline has ane not match fail,but no rollback)

Nested stages,empty stages

cMQL allows nested stages that flattens, nil and empty stages that ignores.

(def x? false)
(defn f [] [stage2 stage3])
(q :testdb.testcoll
(if x? stage1)
(f))
Pipeline will become [stage2 stage3] (nil removed,stages flatten)
It will run as if it was
(q :testdb.testcoll
stage2
stage3)