datomic

Ask questions on the official Q&A site at https://ask.datomic.com!
2021-05-17T08:17:56.153700Z

Hello ! I have a 3 questions about sorting. There is a fairly large collection of photos, each photo has a ‘photo/taken-at’ attribute with value type instant. I want to retrieve 100 photos ordered by taken-at potentially in reverse chronology. What is the idiomatic way to achieve that ? So far I’ve managed to do it using ‘index-pull’ which also has offset, limit and reverse options. Is this the way to do it ? Then, if I want to find a specific photo title in the oldest 100 photos, I would first retrieve the ids using index-pull, then perform a parameterized :find using those ids and the substring as parameters to the query. Alternatively, if I want to find the title in all photos, I first perform the query, then do a sort-by :taken-at on the results. So 3 questions really, but all related :). Is my thinking correct? Thank you !

florinbraghis 2021-05-19T13:29:07.001900Z

Thank you !

joshkh 2021-05-17T09:03:43.153900Z

i've changed the ident name of the attribute below, but other than that it looks like this

#:db{:id          715,
     :ident       :album/artist,
     :valueType   #:db{:id 20, :ident :db.type/ref},
     :cardinality #:db{:id 35, :ident :db.cardinality/one},
     :doc         "A reference to the artist of an album"}

joshkh 2021-05-17T09:06:21.154100Z

i don't know if it's related but 715 in my original post would have likely been pointing to a composite tuple entity with a uniqueness constraint by identity

pyry 2021-05-17T12:16:48.154300Z

1. Can't claim to vouch for a huge user base, but I'd say that is indeed idiomatic. A good choice, at any rate.

pyry 2021-05-17T12:22:56.154500Z

2. That should work. I guess you could also just add the photo title to the :selector and filter "by hand".

pyry 2021-05-17T12:24:22.154700Z

3. Again, I think you could just add the photo title to the :selector instead?

Joe Lane 2021-05-17T14:04:59.154900Z

@jeroen.dejong If you pass in sets of eids instead of lookup refs it appears to do what you're after.

(d/q {:query '{:find [(pull ?parent [:person/name]) (pull ?child [:person/name])]
               :in   [$ [?parent ...] [?child ...]]
               :where [[?child :person/parent ?parent]]}
      :args  [(d/db conn)
              (into #{}
                    (map #(->> % (d/pull (d/db conn) [:db/id] ) :db/id)
                         #{[:person/name "pete"]}))
              (into #{}
                    (map #(->> % (d/pull (d/db conn) [:db/id] ) :db/id)
                         #{[:person/name "frank"]}))]})
;; Returns
;; => [[#:person{:name "pete"} #:person{:name "frank"}]]

2
2021-05-17T14:11:16.155100Z

Nice! I guess I can also use datomic.api/entid in the query to resolve the lookup refs. I initially expected both collection bindings to resolve the lookup refs, but it seems to do 1 collection at most. Is that intended?

Joe Lane 2021-05-17T14:17:21.155400Z

I'll be creating an internal story to investigate this more deeply but for now you should consider it expected behavior.

1👍1
Joe Lane 2021-05-17T14:31:08.155600Z

In the old or the new db?

joshkh 2021-05-17T14:33:16.155800Z

this is all in the old db before we get to the part of replaying the tx in the new db

Joe Lane 2021-05-17T14:43:18.156200Z

@joshkh Is this on dev-local, cloud, on-prem? Can you send back a report of running: 1. (d/pull (d/db conn) '[*] 69269232556469022) 2. (d/pull (d/as-of (d/db conn) 64288) '[*] 69269232556469022) 3. (d/pull (d/as-of (d/db conn) 64289) '[*] 69269232556469022) 4. (d/pull (d/as-of (d/db conn) 64290) '[*] 69269232556469022) 5. (d/pull (d/as-of (d/db conn) 64291) '[*] 69269232556469022) You can dm me or send this to support.