Commands

cMQL can be used in 2 ways

  • cMQL commands, like MQL commands (here we focus on this way)
  • driver methods with cMQL arguments

cMQL supports more commands, here are some of them.

Insert

Single document
(insert :testdb.testcoll doc option1 option2 ...)
Bulk insert
(insert :testdb.testcoll [doc1 doc2 ...] option1 option2})

Aggregate

()->filters {}->addfields []->project Pipeline stages can be nil(useful to generate stage on condition) or nested(usefull to generate multiple stages)

(q :testdb.testcoll
(>_ :age 25)
(=_ :gender 'female') ; filters =>1 match stage
{:pass (>_ :grade 5)} ; addFields
(group :hairColor ; _id renamed to hairCorl
{:count (sum- 1)})
[:count] ; project,keep only count
(sort- :!count) ; sort descending
(skip 2)
(limit 1)
{:allowDiskUse true})

Cursor

cMQL uses the driver cursor object.
So its commands returns normal driver cursors.

At first versions of cMQL there were implementatiosn of cursors using multiple getMore
But this approach was abandonded and cursor drivers are kept.

Find

Find is a subset of aggregate
filters/project/sort/skip/limit as if it was pipeline stages
(they are auto converted to find command options)
The rest are options

(fq :testdb.testcoll
(>_ :spent 150)
(sort- :!spent)
[:!_id :spent {:aspent (+_ :spent 20)}]
(skip 5)
(limit 1)
{:singleBatch true})

Find and Modify

Find and Modify as one step
query/update/sort as if it was pipeline stages
The rest are options
If many match the first document is choosen

Document as filter is allowed only in Update/Find Modify and only if {upsert :true}

Call

Find-Modify (no upsert)
(find-and-modify :testdb.testcoll
(=_ :name 'MongoDB')
{:name (str- :name '-with-id=1')}
(sort- :_id)
(fields-o :!_id :name)
(new-o))
Upsert (when upsert true => first argument doc(only then))
(find-and-modify :testdb.testcoll
{:_id 4}
{:name (if- (exist?- :name)
(str- :name '-with-id=4')
'new-name')}
{:upsert true} ;; upsert => first argument document
(fields-o :!_id :name)
(new-o))

Delete

(delete :testdb.testcoll (dq ...) (dq ..) opt1 opt2 ...)
(delete :testdb.testcoll [(dq ...) (dq ..)] {:ordered true} ...)

Each dq(member of deletes) can have many filters The rest are options (:limit/:collation/:hint/:comment)

(dq filter1
filter2
...
option1
option2)

Example

(delete :testdb.testcoll
(dq (=_ :name "MongoDB")
{:limit 1})) ;;{:limit 0} is the default

Update

Update documents using one or more update queries uq Update many is the default {:limit 0}

(to update nested arrays/documents see)

(update- :testdb.testcoll (uq ...) (uq ..) opt1 opt2 ...)
(update- :testdb.testcoll [(uq ...) (uq ..)] opt1 opt2 ...)

Each uq will be a member of :updates [] see update command

uq works only with pipeline updates stage=$addFields=$set/$project/$unset/$replaceRoot=$replaceWith

(uq filter1/document(if upsert)
filter2
stage1
stage2
...
option1
option2)

Document as filter is allowed only in Update/Find Modify and only if {upsert :true}

Example

No upsert
(update- :testdb.grades
(uq (=_ :_id 2)
{:grades (map- (fn- [:grade-] (inc- :grade-)):grades)}))
Upsert(if upsert true => document always as first argument)
(update- :testdb.grades
(uq {:_id 4} ; q=the first document,only if upsert
{:grade (if- (exist?- :grades)
(inc- :grade)
0)}
{:upsert true})
{:ordered true})

Count

Count documents with optional query on them
Can be done with aggregation
query/limit/skip use as aggregate stages

(q-count- :testdb.testcoll
(=_ :dept 'A') ; filters like aggregation
(skip 1)
(limit 1))

Dinstict

Distinct a field,make it an array,with optinal query first
Can be done with aggregation

(distinct-c :testdb.testcoll
(not=_ :dept 'B')
{:key 'dept'})