There were several improvements made to db
this release:
- smarter
insert
/update
/delete
- join support in
from
andfind-by
- plural or singular table names work just make sure foreign keys match the table name:
accounts_id
vsaccount_id
for a plural or singular table name
Smarter insert/update/delete
This works just like before, but the secret sauce is in the metadata (just :db/table
that gets returned from every query). You can now do things like this:
(def account (db/insert :accounts {:name "sean"})) ; # => {:name "sean" :db/table :accounts :id 1}
(def account (db/update account {:name "@sean"})) ; # => {:name "@sean" :db/table :accounts :id 1}
(db/delete account) ; # => {:name "@sean" :db/table :accounts :id 1}
Similarly, fetch
, fetch-all
, find
, find-by
and from
all return the :db/table
key and work with the transaction functions too!
(def a (db/find :account 1))
(db/update a {:name "new name"})
You don't have to specify a table if you already have a dictionary with :db/table
!
Joins
This is the really cool part, you can not only return joined records with from
like so:
(db/from :accounts :join :todos) ; # => [{:name "sean" :id 1 :db/table :accounts :todos/id 1 :todos/name "todo #1"}]
You can also group them into their own array with :join/many
(db/from :accounts :join/many :todos) ; # => [{:name "sean" :id 1 :db/table :accounts :todos [{:id 1 :name "todo #1"}]}]
Similarly you can do a one
join where you know the foreign key column is in the queried table:
(db/from :todos :join/one :accounts) ; # => [{:name "todo #1" :id 1 :db/table :todos :account {:id 1 :name "sean"}}]
There are some current gotchas when joining:
- You can't join more than one table
join/one
attempts to change the table name to singular if it isn't already::accounts
becomes:account
join/many
attempts to pluralize the table name in the resulting rows::account
->:accounts
- This only works for columns named
{{table}}_id
, there is no way to specify columns not named after the table yet