Fork me on GitHub
#datomic
<
2024-03-01
>
Akane14:03:28

hi everyone! i'm a new clojure user who is trying out datomic, can anyone help me understand what the schema field :db/cardinality does? i don't get what it means or when to use it..

favila14:03:35

One means assertions automatically retract whatever is there, and map projections of entities encode values “bare” without a collection wrapper

favila14:03:44

Many means the opposite

favila14:03:53

IOW one means you can only assert a single value at a time for that attr on a given entity

Akane14:03:41

thanks for the answer, but i'm still pretty new to everything, could you explain what is retract and what is a collection wrapper

favila15:03:02

Perhaps you would be better served by following the tutorial?

Akane00:03:02

alright, thanks

jjttjj17:03:21

I'm trying to make a transaction and then find (for example) all new users in the db as a result of that transaction. My understanding is that the first method is more generally applicable, and the latter will only work if you don't need to get any data that is not in that transaction (due to the "subtlety" described here: https://docs.datomic.com/cloud/time/filters.html#since)? Any other obvious approaches I'm missing?

(let [{:keys [db-after db-before tx-data] :as result}
        (d/transact conn {:tx-data [{:user/id 1}]})]
    (d/q '[:find (pull ?u [*])
           :in $ $before
           :where
           [$ ?u :user/id ?uid]
           (not [$before ?u :user/id ?uid])]
      db-after db-before))
(let [{:keys [db-after db-before tx-data] :as result}
        (d/transact conn {:tx-data [{:user/id 1}]})]
    (d/q '[:find (pull ?u [*])
           :where [?u :user/id ?uid]]
      (d/since db-after (:basisT db-before))))

favila17:03:06

Inspect tx-data directly:

(let [{:keys [db-after tx-data] :as result}
      (d/transact conn {:tx-data [{:user/id 1}]})]
  (d/q '[:find (pull ?u [*])
         :in $ $tx-data
         :where
         [?attr :db/ident :user/id]
         [$tx-data ?u ?attr _ _ true]]
       db-after tx-data))
Or possibly more efficient if tx-data may be big (avoids re-sending the tx-data back):
(let [{:keys [db-after tx-data] :as result}
      (d/transact conn {:tx-data [{:user/id 1}]})
      user-attr-id (ffirst (d/q '[:find ?attr
                                  :where [?attr :db/ident :user/id]]
                                db-after))
      created-user-eids (into []
                              (keep
                               (fn [[e a _v _tx added?]]
                                 (when (and added? (== a user-attr-id))
                                   e)))
                              tx-data)]
  (d/q '[:find (pull ?u [*]) :in $ [?u ...]]
       db-after created-user-eids))

🆒 1
favila17:03:34

Unfortunately I think cloud doesn’t have a way to get tx-data from within a query

jjttjj17:03:06

Thanks, I was wondering if the tx-data could be used

favila20:03:37

It doesn’t have tx-ids or tx-data https://docs.datomic.com/pro/query/query.html#tx-ids

✔️ 1
favila20:03:19

if it did, you could do this:

(let [{:keys [db-after] :as result}
      (d/transact conn {:tx-data [{:user/id 1}]})]
  (d/q '[:find (pull ?u [*])
         :in $ ?log ?tx
         :where
         [?attr :db/ident :user/id]
         [(ground true) ?op]
         [(tx-data ?log ?tx) [[?u ?attr _ _ ?op]]]
       db-after (d/basis-t db-after))

favila20:03:14

without sending the tx-data over the wire 2x potentially

favila20:03:40

(This is pointless on on-prem)

cch120:03:44

Yep. I'm frequently frustrated by the obvious cost of doing that for large transactions.

cch120:03:29

I think there is room in the semantics of the subquery function to allow for subqueries against as-of or since databases or logs. Just wish it were there.