Fork me on GitHub

morning folks! last i heard, about;cid=C03RZMDSH, datomic cloud backup/restore was being worked on. is there any news on this front? we’re extremely interested in having a solution.

🍿 1
Jarrod Taylor (Clojure team)15:07:12

Nothing to share publicly at this time. However, I can say for sure it is actively getting a lot of attention.

Daniel Jomphe15:07:56

My guess is that Cognitect is taking its time to develop a solution that'll share as much common parts as it makes sense under the hood for both OnPrem and Cloud. They're also probably trying to make it easy. ...we'll see once public announcements come out.


thanks @U0508JRJC! glad to hear that — i’m eagerly awaiting further news.

Daniel Jomphe16:07:11

Yes Jarrod, the comment is appreciated!

Jarrod Taylor (Clojure team)16:07:23

I am not the only team member looking forward to shouting it from the roof tops when we have something to share 🙂

💯 1
☺️ 1

related, also curious if anyone has any anecdotes, good or bad around community solutions. i’m aware of 2… • fulcrologic/datomic-cloud-backup — haven’t finished reading the source here. it looks robust, but the repo is archived and the README mentions lack of suitability for (unspecified) production needs. • lambdaforge/wanderung — haven’t started looking at this yet, just found mention of it in this channel.

Daniel Jomphe16:07:44

Our project's repo still has the needed code to execute backups and restores based on fulcrologic's solution. I don't remember how well it worked or not, though - I exercised it to some point for sure, but before concluding it could save us in dire situations, we'd need to invest a lot more time in trying it out. And the author, Tony Kay, FWIR, is also waiting upon Cognitect. I think I remember him saying he reached limits and constraints making it so that only Cognitect can provide a robust and practical solution.


thanks! i found some FUD in an earlier thread around tuple-handling with datomic-cloud-backup too, but haven’t had a chance to dig into it.

Daniel Jomphe15:07:40

Two or three team members completed recently. AFAIK they all liked it enough to go through the end. Our most experienced members say they did it in a few hours. Our new member (completely new to Datomic and Clojure) seems to have spent a day.

😎 1
👍 2
Daniel Jomphe16:07:25

They all did before doing Max Datom. You, the old one that's been around for a number of years...

Jarrod Taylor (Clojure team)16:07:53

Thanks for the feedback. That if great to hear 🙂

Daniel Jomphe16:07:14

I wish I had more feedback! I hope I can take some time to do it myself in the next months.


Hi Daniel, your wish becomes true 🙂 here is some feedback as I am doing it.... LEVEL 3 (d/q '[:find ?v ?e :where [?e :author/first+last-name ?v]] db) === Incorrect Query Response ===

[[["Miguel" "Dvd Rom"] 87960930222171]
 [["Perry" "Farrell"] 87960930222172]
Better warn the user that order is important here
[:find ?e ?v ...]


Your schema txs are syntactically incorrect, there is a closing parenthesis

instead of a closing curly brace in the following segment
{:db/id ":book/name+author"
  :db/ident :book/id+name
  :db/valueType {:db/ident :db.type/tuple)
  :db/cardinality {:db/ident :db.cardinality/one}
  :db/unique {:db/ident :db.unique/identity}
  :db/tupleAttrs [:book/id :book/name]}


Level 5 Replace the * pattern with

:book/name {:book/author [:author/first-name :author/last-name]}
to retrieve the desired attributes. I would prefer replace [*] with
[:book/name {:book/author [:author/first-name :author/last-name]}]
Otherwise it's a bit confusing for the user


Level 6 Modify the query to return any entities referencing the id in the query as a value for :book/author using the underscore prefix syntax.

(d/q '[:find (pull ?e [:book/_author])
       :where [?e :author/id #uuid "14E86ACF-000B-463E-90CB-CEA0927A97DA"]] db)

=== Incorrect Query Response ===
[[{:book/_author [{:db/id 87960930222175} {:db/id 87960930222176}]}]]
=== Expected Query Response ===
[[{:author/first-name "Napoleon",
   :author/last-name "Desktop",
   :book/_author [{:db/id 87960930222175} {:db/id 87960930222176}]}]]
My query above does exactly what the tutorial is asking, add in the exercise "`retrieve the first and last names of the author and any entities.....` but that is what tutorial takes as a correct answer
(d/q '[:find (pull ?e [:author/first-name :author/last-name :book/_author])
       :where [?e :author/id #uuid "14E86ACF-000B-463E-90CB-CEA0927A97DA"]] db)


Level 8

(d/q '[:find (pull ?e [:author/first-name :author/last-name])
       :in $ ?author-id
       :where [?e :author/id ?author-id]] db)
Max Datom informs me Human, you must include the author-id as an argument to the query. That's because I did not see the
(def author-id #uuid "35636B79-EE46-4447-8AA7-3F0FB351C45C")
and it's a bit confusing that both the argument and the input variable has the same name author-id. Hmmm
(def author-id #uuid "35636B79-EE46-4447-8AA7-3F0FB351C45C")

(d/q '[:find (pull ?e [:author/first-name :author/last-name])
       :in $ ?author-id
       :where [?e :author/id ?author-id] db author-id)
Max Datom message EOF while reading I had to do refresh and renter the query
(d/q '[:find (pull ?e [:author/first-name :author/last-name])
       :in $ ?author-id
       :where [?e :author/id ?author-id]] db author-id)


Level 10 I am presenting you with your very own Max Datom (TM) polo shirt 🙂 Sure send it to my home address please.... ... I will not spoil the fun writing the query here but again order matters

:find (count ?posts) ?user-name 
does not allow you to continue in the next level...


Level 11 That is interesting....

(d/q '[:find  (count ?post) ?user-name
       :where [?user :user/first+last-name ?user-name]
              (not [?post :post/dislikes ?user])] db)
:db.error/insufficient-binding [?post] not bound in not clause: (not-join [?user ?post] [?post :post/dislikes ?user]) I am trying to understand why as this query without negation works fine although it's not the correct response
(d/q '[:find  (count ?posts) ?user-name
			 :where [?user :user/first+last-name ?user-name]
			 [?posts :post/dislikes ?user]
			 ] db)
=== Incorrect Query Response ===
[[3 ["Segfault" "Larsson"]]]
=== Expected Query Response ===
[[1 ["E. L." "Mainframe"]]]
OK I read documentation, it seems that this is a not-join case because ?posts is in the :find var clause. So I guess the example given in that level is misleading, correct ? Oh boy that doesn't work too
(d/q '[:find  (count ?post) ?user-name
       :where [?user :user/first+last-name ?user-name]
       (not-join [?post] [?post :post/dislikes ?user])] db)

Jarrod Taylor (Clojure team)19:07:26

Thanks for all of the feedback. I don’t believe the example is misleading and the solution does indeed use a not clause.


Perhaps I am confused from the documentation and the error message... :db.error/insufficient-binding [?post] not bound in not clause: (not-join [?post] [?post :post/dislikes ?user]) why it complains about my answer then, where is my mistake ?

Jarrod Taylor (Clojure team)19:07:50

Try adding a clause to bind ?posts for your ?user then only use [?posts :post/dislikes] in the not clause.


OK yes I got it right this time, thanks for the tip, and I will not write the answer to spoil the fun.... but it seems it deviates a bit from the example in Level 12. Second, my tip for someone that tries to solve it is to understand that negation here implies set difference operation. That is explained well in Datomic documentation -


Level 12 is more or less straight forward, I solved it, but I still have some problem to understand pull syntax and why it requires vector for [:post/comments :xform ...] in order to convert it to another key-value pair in the result set. To be continued...


Level 15 is tough, one has to see the response and then try to replicate it with the correct query format...


Done, I reached Level 17. I think the fraud detection scenario (L15, L16, L17) was not clear, i.e. what account they tried to conceal, for what purpose and which account they present as the legitimate one. In Level 15 it says "That transfer looks like we would expect, but why did the funds not make it to Mr. CD? Continue to level 16 to investigate further." But the response shows that transfer destination was Mr. Muhammad CD and therefore it appears that funds were transferred to him... That is what I figured out: Fraudulent account of user Spammy the Bull (destination of original transfer in the past) Legitimate account of user Muhammad CD (what appears to be the current destination of transfer) Anyway, in overall it was a good experience playing with Max Datom and I would like to thank @U0508JRJC for his time to share this tutorial with the rest of us