datomic

Ask questions on the official Q&A site at https://ask.datomic.com!
joshkh 2021-06-20T15:59:41.253900Z

the other day i asked about how to audit which query rules are satisfied and favila had a nice suggestion to use ground to return some known value. that works when my "top level" rule returns a grounded value, however i'd like to also audit nested rules as well. any idea how i can aggregate some grounded values from each rule? here is a non-working example that returns an empty result because i think the bound value of ?rule in the parent rule fails to unify on the different bound values in the nested rules.

(let [rules '[[(is-blue ?item ?rule)
               [(ground :is-blue) ?rule]
               [?item :item/color "blue"]]

              [(is-in-stock ?item ?rule)
               [(ground :is-in-stock) ?rule]
               [?item :item/inStock? true]]

              [(blue-items-in-stock ?item ?rule)
               [(ground :blue-items-in-stock) ?rule]
               (is-blue ?item ?rule)
               (is-in-stock ?item ?rule)]]]

  (d/q '{:find  [?item (distinct ?rule)]
         :in    [$ %]
         :where [(blue-items-in-stock ?item ?rule)]}
       (d/db conn) rules))
=> []
ideally i would end up with something like this:
=> [[92358976734084 #{:blue-items-in-stock :is-blue :is-in-stock}]]

joshkh 2021-06-21T17:49:28.277500Z

well this is exactly what i was looking for. thank you @lanejo01!

Joe Lane 2021-06-21T17:50:58.277700Z

NP, I just wish I would have thought of it sooner 😂 . Definitely could have used this over the years.

refset 2021-06-20T16:32:39.254Z

> [?item :item/inStock? true ?rule] is that 4th element intended?

joshkh 2021-06-20T16:51:19.254400Z

oops, that was just a typo in the example. thanks for pointing it out.

1👌
Joe Lane 2021-06-20T17:49:27.255100Z

No, it’s an address, addresses can change.

Joe Lane 2021-06-20T19:00:19.255800Z

Use clojure to construct the query as data

(defn query-players
  [db rules player-name wants-is-player-rule?]
  (->
   (cond->
       '{:find  [?player]
         :in    [$ % ?player-name]
         :where [[?player :player/name ?player-name]]}
     wants-is-player-rule? (update :where conj '(?is-player ?player)))
   (d/q db rules player-name)))

(query-players (d/db conn) the-rules "player1" true)

kenny 2021-06-20T19:03:20.257100Z

Oh interesting. When does it change at the moment? What’s the migration strategy to go from one format to another?

Joe Lane 2021-06-20T19:05:05.257300Z

At the moment it doesn't, but you asked if you can rely on the endpoint address "ALWAYS" following that format.

kenny 2021-06-20T20:29:59.258Z

I see. If it were to change, how could that be done safely?

Joe Lane 2021-06-20T20:47:18.259500Z

It’s just a different string. What if the endpoint had a uuid in it? I’m not sure what you mean by “safely”.

kenny 2021-06-20T20:56:21.261Z

If it were to change, client applications would need to know about which endpoint to point to. By safely I mean informing the client application which endpoint it should use before and after the switch.

Joe Lane 2021-06-20T22:00:29.262900Z

“Client applications” meaning not ions?

kenny 2021-06-20T22:00:43.263200Z

Correct

Joe Lane 2021-06-20T22:01:01.263800Z

How do they know what endpoint to hit right now?

kenny 2021-06-20T22:11:46.264900Z

Statically defined string at startup. Seems like a switch of that endpoint would be require application downtime.

Joe Lane 2021-06-20T22:45:48.269200Z

Doubtful. That statement is only true because you aren’t using a mechanism to dynamically update that endpoint and the datomic client using it.

Joe Lane 2021-06-20T22:50:55.270600Z

Imagine switching the query groups your client applications point to with zero downtime. How would you do it?