Notation allows cMQL to have simple syntax for more see Notation

Source code

The code is seperated in 3 parts

  1. cMQL core, commonly used code (cljc)
  2. cMQL-j for the the Java driver,cMQL-js for the nodejs driver


  1. operators
  2. stages
  3. arguments (arguments to be used in the driver methods)
  4. commands (generate and run MQL commands)

cMQL for the most part is one to one, translate of cMQL to MQL

For example

(defn * [& exprs]
{"$multiply" (vec exprs)})

Operators are implemented in

  • cmql/operators.cljc
    see also Operators and TODO THE API LINK ON OPERATORS
  • cmql/stages.cljc
    see also Stages and TODO THE API LINK ON OPERATORS
  • cmql/options.cljc

Arguments are implemented in

  • cmql_j/arguments.clj (cMQL-j on java driver)
  • cmql_js/arguments.cljs (cMQL-js on node driver) cmql_js/arguments.clj (macros of cMQL-js on node driver)


Commands are implemented in

  • cmql/read_write.cljc
  • cmql/administration.cljc
  • cmql/diagnostic.cljc
  • cmql/roles.cljc
  • cmql/users.cljc

*Commands are meant to be used if the driver is missing some command or its hard to use In general cMQL doesn't try to replace the driver way, but to make the queries easier

Seeing the API and the docstring can many times are enough to know how to use a cMQL operator.
MongoDB documentation can help on how to use the MQL operator, and most of the times its the same with the cMQL operator.

Commands and arguments

  1. cMQL commands
(q zips
(= :state "TX")
(group :city {:totalPop (sum :pop))
[:!_id :totalPop]
(sort :!totalPop)
{:allowDiskUse true})
(update- :sample_training.grades
(uq (= :student_id 10000)
{:comment "You should learn MongoDB!"}
{:multi false}))

Those that return cursors,use the driver method
All the others for example update uses runCommand()

cMQL commands generate MQL commands,they are easy to use and programmable
And completly portable,for example the above runs unchanged in Java/Nodejs

*cMQL provided a cursor implementation,but it has being removed,because it made things more complex to have 2 types of cursors so driver cursors are kept only

  1. Driver methods, interop with cMQL arguments
(.aggregate zips
(p (= :state "TX")
(group :city {:totalPop (sum :pop))
[:!_id :totalPop]
(sort :!totalPop)))

We use the argument wrappers

  • p for pipelines
  • f for filters
  • o for options


cMQL is meant to be learned by examples using cMQL-Play cMQL-Play allows us to us to use aggregation and pipeline updates (a subset of cMQL)

cMQL project examples

*Clojure-app has the most examples, the rest apps are mostly a sample on how to run cMQL.
They also provide an implementation of MongoDB quickstart in cMQL.

cMQL operators/stages/commands are part of the cMQL core and generate MQL operators/stages/commands.
cMQL arguments are used with the driver methods and are part of cMQL-j or cMQL-js

See also

cMQL enviroment

cMQL methods like q fq,or argument methods like p,f provide an cMQL enviroment.

We can't use cMQL code outside of cMQL enviroment,the bellow wont work

(defn mystage []
(group :city {:totalPop (sum :pop)))
(p (= :state "TX")
[:!_id :totalPop]
(sort :!totalPop))

We need cmql macro to make it work (wrap any valid code around cmql)

(defn mystage []
(cmql (group :city {:totalPop (sum :pop))))
(p (= :state "TX")
[:!_id :totalPop]
(sort :!totalPop))

Clojure core

If you want to use a clojure core function that cMQL hides, inside a cMQL enviroment you should use it with its namespace,for example

c here used as an alias for clojure.core

(p (= :state (c/str "T" "X"))
[:!_id :totalPop]
(sort :!totalPop))

If we need to write alot of clojure code we make seperate function call to avoid the namespace. Most of the time there almost all code is clojure or almost all code is cMQL so its easy to be mixed.