Fork me on GitHub
#datomic
<
2022-08-22
>
jumar06:08:32

Going through the Max Datom tutorial again, https://max-datom.com/#/40A6D16E-2FB4-4F8E-898F-33BF6F9CC4E0. While my query got accepted, I have some troubles to pull all the data they show. Specifically, I would like to pull all the attributes from a nested entity. More details in the thread.

jumar06:08:17

This is the initial query that needs to be extended:

(def transfer-id #uuid "59B9C791-74CE-4C51-A4BC-EF6D06BEE2DB")
(d/q '[:find (pull ?e [*])
         :in $ ?transfer-id
         :where [?e :transfer/id]] db transfer-id)
They say: > Pull all :transfer/from and :transfer/to data including :account/owner for a recently reported transfer :transfer/id #uuid "59B9C791-74CE-4C51-A4BC-EF6D06BEE2DBA" (note the uuid here is incorrect, it has extra "A")

jumar07:08:39

After quite a bit of struggle, I ended up with this:

(d/q '[:find (pull ?transfer [*
                                {:transfer/from [* {:account/owner [*]}]}
                                {:transfer/to [* {:account/owner [*]}]}])
         :in $ ?transfer-id
         :where
         [?transfer :transfer/id ?transfer-id]
         [?transfer :transfer/to ?to-account]
         [?transfer :transfer/from ?from-account]] db transfer-id)
Thinking about this more, the difference I see on my machine is might be because I have incomplete data They show this result:
[[{:db/id 92358976733273,
     :transfer/from
     {:db/id 92358976733272,
      :account/balance 8900,
      :account/id #uuid "5164b8da-2fe4-41da-a5fd-1a697be1d2dd",
      :account/owner
      {:db/id 92358976733269,
       :user/first-name "Sonny",
       :user/id #uuid "afb83133-3a2e-40ce-91f8-2de4f61361de",
       :user/last-name "Diskon"}},
     :transfer/id #uuid "59b9c791-74ce-4c51-a4bc-ef6d06bee2db",
     :transfer/to
     {:db/id 92358976733271,
      :account/balance 2300,
      :account/id #uuid "d381dc80-c582-45eb-89e9-f6e188a71a29",
      :account/owner
      {:db/id 92358976733268,
       :user/first-name "Muhammad",
       :user/id #uuid "bfe00de4-bc19-4395-ba3b-2384ecf1a569",
       :user/last-name "CD"}}, 
     :transfer/amount 1000}]]
I get the same but :account/owner entities aren't expanded (they are only db ids).

jumar07:08:12

So a different question: is there a simpler way to achieve what I'm after. Again, my query is this:

(d/q '[:find (pull ?transfer [*
                                {:transfer/from [*]}
                                {:transfer/to [*]}])
         :in $ ?transfer-id
         :where
         [?transfer :transfer/id ?transfer-id]
         [?transfer :transfer/to ?to-account]
         [?transfer :transfer/from ?from-account]] db transfer-id)

thumbnail08:08:58

You don’t need to bind ?to-account or ?from-account, but you do need to pull :account/owner too in order to get the correct query response

jumar08:08:14

Ah, of course - the other two clauses were a relict from earlier experiment. I'm not sure I got the part about "need to pull :account/owner" - how would I do that? This is what I have right now

(d/q '[:find (pull ?transfer [* {:transfer/from [*] :transfer/to [*]}])
         :in $ ?transfer-id
         :where [?transfer :transfer/id ?transfer-id]]
       (db) transfer-id)

thumbnail10:08:33

You can add {:account/owner [*]} to the pull expression for both transfer/from and transfer/to

jumar10:08:37

It doesn't seem to work or I didn't understand you. The first query already works and is what I have. The second one doesn't:

(d/q '[:find (pull ?transfer [* {:transfer/from [*] :transfer/to [*]}])
         :in $ ?transfer-id
         :where [?transfer :transfer/id ?transfer-id]]
       (db) transfer-id)
  ;; => [[{:db/id 92358976733273,
  ;;       :transfer/id #uuid "59b9c791-74ce-4c51-a4bc-ef6d06bee2db",
  ;;       :transfer/from
  ;;       {:db/id 92358976733272,
  ;;        :account/id #uuid "5164b8da-2fe4-41da-a5fd-1a697be1d2dd",
  ;;        :account/balance 8900,
  ;;        :account/owner #:db{:id 92358976733269}},
  ;;       :transfer/to
  ;;       {:db/id 92358976733271,
  ;;        :account/id #uuid "d381dc80-c582-45eb-89e9-f6e188a71a29",
  ;;        :account/balance 2300,
  ;;        :account/owner #:db{:id 92358976733268}},
  ;;       :transfer/amount 1000}]]

  (d/q '[:find (pull ?transfer [* {:account/owner [*]}])
         :in $ ?transfer-id
         :where [?transfer :transfer/id ?transfer-id]]
       (db) transfer-id)
  ;; => [[{:db/id 92358976733273,
  ;;       :transfer/id #uuid "59b9c791-74ce-4c51-a4bc-ef6d06bee2db",
  ;;       :transfer/from #:db{:id 92358976733272},
  ;;       :transfer/to #:db{:id 92358976733271},
  ;;       :transfer/amount 1000}]]

thumbnail11:08:49

The pull expression you’re looking for is something like this:

[* {:transfer/from [*, {:account/owner [*]}] :transfer/to [*, {:account/owner [*]}]}]

thumbnail11:08:10

that way you’re also pulling all the attributes in the account/owner reference

jumar12:08:44

Oh, I see - I tried that before and it didn't make a difference, at least as far as the tutorial goes. It seems like the simpler version returned the exact same data: [* {:transfer/from [*] :transfer/to [*]}]

thumbnail12:08:08

I passed the challenge with the pull expression i posted though 👀

jumar18:08:25

What I meant is that they both work 🙂 So I lean towards the shorter version.

thumbnail19:08:27

Maybe im misunderstanding, but your pe wont pull the attributes of the account owner, which is required by the challenge, no :thinking_face:?

jumar03:08:57

You are right 🙂 I thought my query was enough because Max Datom accepted it - i'm not sure why. It pretended it returns all the data but in fact it doesn't. After I added the relevant user (:account/owner) data to my local db I can clearly see, that my query doesn't return any data about :account/owner apart from :db/id. If I add these extra bits then it works. This is then my final version:

(d/q '[:find (pull ?transfer [* {:transfer/from [* {:account/owner [*]}]
                                   :transfer/to [* {:account/owner [*]}]}])
         :in $ ?transfer-id
         :where [?transfer :transfer/id ?transfer-id]]
       (db) transfer-id)
  ;;=>
  [[{:db/id 92358976733273,
     :transfer/id #uuid "59b9c791-74ce-4c51-a4bc-ef6d06bee2db",
     :transfer/from
     {:db/id 92358976733272,
      :account/id #uuid "5164b8da-2fe4-41da-a5fd-1a697be1d2dd",
      :account/balance 8900,
      :account/owner
      {:db/id 92358976733269,
       :user/id #uuid "afb83133-3a2e-40ce-91f8-2de4f61361de",
       :user/first-name "Sonny",
       :user/last-name "Diskon",
       :user/first+last-name ["Sonny" "Diskon"]}},
     :transfer/to
     {:db/id 92358976733271,
      :account/id #uuid "d381dc80-c582-45eb-89e9-f6e188a71a29",
      :account/balance 2300,
      :account/owner
      {:db/id 92358976733268,
       :user/id #uuid "bfe00de4-bc19-4395-ba3b-2384ecf1a569",
       :user/first-name "Muhammad",
       :user/last-name "CD",
       :user/first+last-name ["Muhammad" "CD"]}},
     :transfer/amount 1000}]]
So takeaway is that * basically pulls only the direct entity's attributes, but not attribute of entity's components?

thumbnail04:08:35

🙂 nice, glad you managed! And yes that's basically it. This is the relevant part of the doc https://docs.datomic.com/cloud/query/query-pull.html#nesting

Nedeljko Radovanovic21:08:26

Hey people, I am having a big time issue that I can't fix.. So I want to switch from mem database to a dev-local.. but when I downloaded cogni dev tools and finished their tutorial, in code I get this message.. Execution error (FileNotFoundException) at datomic.client.api.impl/serialized-require* (impl.clj:16). Could not locate datomic/dev_local/impl__init.class, datomic/dev_local/impl.clj or datomic/dev_local/impl.cljc on classpath. Please check that namespaces with dashes use underscores in the Clojure file name. I tried to find a fix on google and in documentation but I could not find a solution, I am not using datomic cloud, I am trying to connect via transactor locally. I even followed this tutorial https://www.youtube.com/watch?v=QYJeHyd47tM&amp;t=278s&amp;ab_channel=EngineeringwithV for connection dev-local and It still doesn't work.. I hope someone know the solution and I thank you for your time...

Jarrod Taylor (Clojure team)02:08:51

First make sure you have the dependency specified correctly in your deps.edn file. Something along the lines of

{:paths ["src"]
 :deps {com.datomic/dev-local {:mvn/version "1.0.243"}}}