rql is a bunch of functions for working with a collection of records. It contains SQL like functions for selecting / removing records from a collection of records.
If you're using leiningen just add [rql "1.1.0"] to your dependencies.
Given the following definitions
(defrecord Person [first-name last-name age])
(def maarten (Person. "Maarten" "Hus" 21))
(def danny (Person. "Danny" "Kieanu" 21))
(def cornel (Person. "Cornel" "Berberus" 22))
(def ronald (Person. "Ronald" "Chocolate" 19))
(def persons [maarten danny cornel ronald])
(where persons :age 21)
Results in:
(#Person{:first-name "Maarten", :last-name "Hus", :age 21} #Person{:first-name "Danny", :last-name "Kieanu", :age 21})
(where persons :first-name "Maarten")
Results in:
(#Person{:first-name "Maarten", :last-name "Hus", :age 21})
(delete persons :age 21)
Results in:
(#Person{:first-name "Cornel", :last-name "Berberus", :age 22} #Person{:first-name "Ronald", :last-name "Chocolate", :age 19})
(delete persons :last-name "Kieanu")
Results in:
(#Person{:first-name "Maarten", :last-name "Hus", :age 21} #Person{:first-name "Cornel", :last-name "Berberus", :age 22}
#Person{:first-name "Ronald",:last-name "Chocolate", :age 19})
(insert persons (Person. "Tom" "Sawyer" 35) (Person. "Adam" "Sawyer" 35))
Results in:
(#Person{:first-name "Maarten", :last-name "Hus", :age 21} #Person{:first-name "Danny", :last-name "Kieanu", :age 21}
#Person{:first-name "Cornel", :last-name "Berberus", :age 22} #Person{:first-name "Ronald", :last-name "Chocolate", :age 19}
#Person{:first-name "Tom", :last-name "Sawyer", :age 35} #Person{:first-name "Adam", :last-name "Sawyer", :age 35})
(update persons {:age 10})
Results in:
(#Person{:first-name "Maarten", :last-name "Hus", :age 10} #Person{:first-name "Danny", :last-name "Kieanu", :age 10}
#Person{:first-name "Cornel", :last-name "Berberus", :age 10} #Person{:first-name "Ronald", :last-name "Chocolate", :age 10})
(update persons {:last-name "Goose"} :last-name "Hus" :first-name "Maarten")
Results in:
(#Person{:first-name "Maarten", :last-name "Goose", :age 21} #Person{:first-name "Danny", :last-name "Kieanu", :age 21}
#Person{:first-name "Cornel", :last-name "Berberus", :age 22} #Person{:first-name "Ronald", :last-name "Chocolate", :age 19})
(sort persons :first-name)
Results in:
(#Person{:first-name "Cornel", :last-name "Berberus", :age 22} #Person{:first-name "Danny", :last-name "Kieanu", :age 21}
#Person{:first-name "Maarten", :last-name "Hus", :age 21} #Person{:first-name "Ronald", :last-name "Chocolate", :age 19})
You can also add you own operator:
(sort persons > :age)
Results in:
(#Person{:first-name "Cornel", :last-name "Berberus", :age 22} #Person{:first-name "Maarten", :last-name "Hus", :age 21}
#Person{:first-name "Danny", :last-name "Kieanu", :age 21} #Person{:first-name "Ronald", :last-name "Chocolate", :age 19})
(group persons :age)
Results in:
( (#Person{:first-name "Ronald", :last-name "Chocolate", :age 19})
(#Person{:first-name "Cornel", :last-name "Berberus", :age 22})
(#Person{:first-name "Maarten", :last-name "Hus", :age 21} #Person{:first-name "Danny", :last-name "Kieanu", :age 21}) )
Update, insert, where, delete and sort-on all have persistent variants ie. update!, insert!, where! delete! and sort-on!. In other words they actually change the collections and doesn't just create new ones. These functions don't take collections but ref's to collections.
For example:
(def persons (ref [maarten danny cornel ronald]))
(update! persons {:age 10})
@persons
Results in:
(#Person{:first-name "Maarten", :last-name "Hus", :age 10} #Person{:first-name "Danny", :last-name "Kieanu", :age 10}
#Person{:first-name "Cornel", :last-name "Berberus", :age 10} #Person{:first-name "Ronald", :last-name "Chocolate", :age 10})
Note that group doesn't have a persistent version because it changes the depth of the collection. Which I think is wrong to persist.