Read Revisited: More Query
First, don't forget to acquire the latest value of the database, after the transaction that added the order.
(def db (d/db conn))
Parameterized Query
Now let's try a more complex query. We would like to be able to suggest additional items to shoppers. We need a query that, given any inventory item, finds all the other items that have ever appeared in the same order.
The "related items" query will have two parameters:
- A database value
- An inventory entity id
Parameters enter query via additional arguments to q, and they are
named by a corresponding :in clause. The special $ name is a
placeholder for the database value.
The query below finds the SKUs for all items that have appeared in an order with SKU-25:
noslide
(d/q '[:find ?sku :in $ ?inv :where [?item :item/id ?inv] [?order :order/items ?item] [?order :order/items ?other-item] [?other-item :item/id ?other-inv] [?other-inv :inv/sku ?sku]] db [:inv/sku "SKU-25"])
=> [["SKU-25"] ["SKU-26"]]
Notice how variables are used to join:
?invis bound on input to the entity id for SKU-25, which- joins to every order
?itemmentioning?inv, which - joins to every
?orderof that?item, which - joins to every
?other-itemin those orders, which - joins to every
?other-invinventory entity, which - joins to all the skus
?sku
Rules
The "related items" feature is so nice that we would like to use it in a bunch of different queries. You can name query logic as a rule and reuse it in multiple queries.
- Create a rule named
ordered-togetherthat binds two variables?inv
and ?other-inv if they have ever appeared in the same order:
noslide
(def rules '[[(ordered-together ?inv ?other-inv) [?item :item/id ?inv] [?order :order/items ?item] [?order :order/items ?other-item] [?other-item :item/id ?other-inv]]])
- Now you can pass these rules to a query, using the special
:inname%,
and then refer to the rules by name:
noslide
(d/q '[:find ?sku :in $ % ?inv :where (ordered-together ?inv ?other-inv) [?other-inv :inv/sku ?sku]] db rules [:inv/sku "SKU-25"])
=> [["SKU-25"] ["SKU-26"]]
So far we have created and accumulated data. Now let's look at what happens when things change over time.