Fork me on GitHub
#datomic
<
2023-09-16
>
Jakub Holý (HolyJak)17:09:54

Hello! I am trying to find out how to sort a list of entities I pulled in a stable order, e.g. in the order of their of their creation (so new ones would be last). But I do not have an explicit timestamp on them. Can I somehow get the tx instant / id associated with an attribute (e.g. the entity’s identity property) when using pull? I guess not but want to make sure. Alternatively, is db/id guaranteed to be ascending? I am using datomic-local 🙏 (I know I can find the tx using d/q but would prefer the complexity of additional query + merging the 2 data sets)

1
favila18:09:22

No on using pull to get tx. Db id is roughly entity creation order if they are all in the same partition. You can sort db id by t using d/tx->t to get creation order

favila18:09:39

The T part of entity ids is ascending and interleaved with transaction Ts

Jakub Holý (HolyJak)18:09:46

Awesome! Thanks a lot!

Jakub Holý (HolyJak)13:10:06

@U09R86PA4 do you know how this works with datomic-local? The datomic.client.api doesn’t have tx->t 🙏

favila15:10:36

The least-significant 42 bits are the t

Jakub Holý (HolyJak)19:10:04

So I guess I just do

(->> entities
     (sort-by #(-> % :db/id (bit-and 2r111111111111111111111111111111111111111111))))
right?

Hendrik21:09:43

I get a weird bevahiour with datomic.peer api. A broader query returns an empty set, but a more specific query returns a non empty set

(ns user)

(comment
  (def db-uri "datomic:")
  (require '[datomic.api :as d])
  (d/create-database db-uri)
  (def conn! (d/connect db-uri))
  @(d/transact conn! [#:db{:ident :my/attr,
                           :valueType :db.type/boolean,
                           :cardinality :db.cardinality/one}])
  (def db (d/db conn!))
  ; query 1
  (d/q '[:find   ?e ?a
         :where
         [?e ?a :my/attr]] db); => #{}
  ; query 2
  (d/q '[:find   ?e
         :where
         [?e :db/ident :my/attr]] db); => #{[72]}
  )
Tested with com.datomic/peer {:mvn/version "1.0.6735"} and an empty project. I would expect that every item of the 2nd query must also appear in the first query. Did anybody observe the same bevahiour?

Ben Kamphaus21:09:14

^ beat me to it, specifically: > Since the attribute itself is dynamic, Datomic does not know that the variable ?reference is guaranteed to refer to a reference attribute, and will not perform entity identifier resolution for ?country. Unable to resolve :country/BE, the query returns no results. referring to example clause: [?artist ?reference ?country]

❤️ 1
Hendrik05:09:27

Thank you so much. So the problem in my first query is, that datomic cannot distinguish, if :gdpr/private is an ident or belongs to an attribute of type keyword. Because of this ambiguity datomic decides to return nothing, right?

Ben Kamphaus15:09:47

[?e ?a :my/attr] for ?a as a dynamic binding, only literal resolution works in the value position (where :my/attr is). you need ?a to be bound to an attribute of type ref in order for the query engine to match values using entity resolution behavior. :my/attr resolving to the entity w/ entity-id that has entity-id :db/ident :my/attr is a little bit of sugar around identity semantics that Datomic facilitates being used in places in the api or query engine, but not in situations where it’s eg computationally prohibitive to do so.

Ben Kamphaus15:09:24

so to be more precise, it’s not ‘datomic decides to return nothing’ but more broadly, datomic does not always guarantee that using the :db/ident of :some/value to refer to an entity will work everywhere, but only in some places. this is one of the situations (`?a` in attribute position not bound/narrowed to a ref attribute) where it does not do extra work behind the scenes to let you shorthand it.

Hendrik15:09:17

Thanks for the explanation 🙂