-
Notifications
You must be signed in to change notification settings - Fork 20
Composable datalog queries
Petter Eriksson edited this page Dec 16, 2017
·
9 revisions
We created a small libraries to easier create and compose datomic queries. Our datomic queries are maps all the way until the query is executed.
{:find <find-pattern>
:where <where-clauses>
:symbols <map-from-symbol-to-value>
:with <with-symbol>
:fulltext <seq of maps describing a full text search>
:rules <seq of functions returning rules>}
;; Given a first name and keywords describing the person, create a
;; query finding users matching the description.
(def query
{:where '[[?e :user/first-name ?first-name]
[?e :user/description ?description]]
:symbols {'?first-name "Jessica"
'[?keywords ...] ["clojure" "dev"]}
:fulltext '[{:attr :user/description
:arg ?keywords
:return [[?e ?description _ ?score]]}]}
;; Given this query, we can now use it in different ways.
(require '[eponai.common.database :as db])
;; Gets the first match by adding :find clause '[?e .]
(db/one-with db query)
;; Gets all matches by adding :find clause [[?e ...]]
(db/all-with db query)
;; Specify our own find pattern:
(db/find-with db (db/merge-query query
{:find [[?user ?description (max ?score)]]})
;; Note: db/merge-query can merge any of the keys, so we can for example
;; more symbols, where-clauses or fulltext searches, any time we want.
- Queries can be merged with other queries using
(merge-query base addition)
. - Values normally passed as extra arguments to
datomic.api/q
is passed to the:symbols
map. - Rules are passed as 0-arity functions that return rules. They are deduped before query is executed.
- Separate and combined functions for pull:
(db/pull db pattern id)
(db/pull-many db pattern ids)
(db/pull-one-with db pattern query)
(db/pull-all-with db pattern query)
- Fulltext search works for both datomic and (normally not supported) datascript. The key takes a list of searches, where each search is a map with
#{:attr :arg :return :db}
where:db
is optional.- :attr - the attribute to search values for
- :arg - symbol providing search string
- :return - a where clause describing the return value with format
[[?entity-id ?value ?tx ?relevance-score]]
- :db - optional db symbol, defaults to
$
We found that we usually just want to return one or many datoms matching the query, so we usually don't supply a find pattern, and instead call our functions one-with
or all-with
, which adds the [?e .]
or [[?e ...]]
find pattern respectively.
Using one-with
and all-with
reads quite nicely in the code as well. If you want to use your own find-pattern, use (db/find-with db query)
.
The functions in the entire eponai.common.database
library is made to work with both datomic and datascript. The functions will do protocol dispatch on the database-connection or database-value argument.