Fork me on GitHub
Matt Butler13:11:46

If there are 2 datums in the same transaction setting a :db.unique/value attribute to the same value do either go through/are they merged or is the tx thrown out completely returning the a db.error/unique-conflict? When processing a large number of transactions for about 1/5 I get value: x already held by: 17592186703132 asserted for: 17592186703135 It seems always to be 3 ids apart. Can this be happening within a transaction or is it that there are 2 transactions being created with the same datum value x.


I found myself normalizing ten statuses (e.g. APPLICATION_COMPLETED) into its own entity, so that instead of storing e.g. :user/status with the value ACCEPTED, I have the entity 'user-status' with all the valid statuses, and :user/status-id referring to that entity with an id. Is this idiomatic in Datomic (I often model it like this in traditional relational databases, but sometimes I don’t because of the improved readability to store it as a plain value).


I changed back to using values. Felt like incidental complexity otherwise.


i have an interesting problem. I want to build a basket with line items in it. I assign the basket to user using identity ref. So subsequent transactions for same user result in only one basket always. So far so good. Problem is now that my Line items collection is actually growing. Is there a way to model cardinality many on a ref in sucha way that it is not duplicating the line items but replaces them?

;Line item
    {:db/id #db/id[:db.part/db]
    :db/ident :item/quantity
    :db/valueType :db.type/long
    :db/cardinality :db.cardinality/one
    :db/doc "Quantity of item"
    :db.install/_attribute :db.part/db}
    {:db/id #db/id[:db.part/db]
    :db/ident :item/part
    :db/valueType :db.type/ref
    :db/cardinality :db.cardinality/one
    :db/doc "Line item ref to product"
    :db.install/_attribute :db.part/db}
    {:db/id #db/id[:db.part/db]
    :db/ident :basket/owner
    :db/valueType :db.type/ref
    :db/unique :db.unique/identity
    :db/cardinality :db.cardinality/one
    :db/doc "the owner of the basket"
    :db.install/_attribute :db.part/db}
    {:db/id #db/id[:db.part/db]
    :db/ident :basket/items
    :db/valueType :db.type/ref
    :db/isComponent true
    :db/cardinality :db.cardinality/many
    :db/doc "Items in the basket"
    :db.install/_attribute :db.part/db}


       :db/id #db/id[:db.part/user]
       ;notice the lookup ref usage to obtain references. Lovely.
       :basket/owner [:user/email ""]
       :basket/items [{:db/id #db/id[:db.part/user]
                    :item/quantity 25
                    :item/part [:part/name “blablaba"]}]


so a transaction above executed multiple times always edits the same basket, but line items grows instead of being totlly replaced ….


@karol.adamiec I believe there was a google group post some time back about implementing a transaction function called assertWithRetractions or something like that


@marshall so in general the upsert niceness ends when cardinality many comes into play? is that correct understanding?


upsert behavior only occurs on cardinality one attributes. the semantic of cardinality many requires that assertions be additive, not replacing


makes perfect sense, thanks! will check out the thread.


(d/transact conn [{:db/id #db/id [:db.part/user]
     :db/ident :assertWithRetracts
     :db/fn #db/fn {:lang "clojure"
                :params [db e a vs]
                :code "(vals (into (into {} (map (comp #(vector % [:db/retract e a %]) first) (datomic.api/q [:find '?v :where [e a '?v]] db))) (into {} (map #(vector % [:db/add e a %]) vs))))"}}])
CompilerException java.lang.RuntimeException: Can't embed object in code, maybe print-dup not defined: [email protected], compiling:(NO_SOURCE_PATH:63:1)


i picked the function from one of the threads, but no idea why it is not installing?


hmm, worked through REST api transaction...


sucess. i can retract cardinality many with that little function, and assert new stuff in.


so back to my original query...


       :db/id #db/id[:db.part/user]
       ;notice the lookup ref usage to obtain references. Lovely.
       :basket/owner [:user/email “"]
       :basket/items [{:db/id #db/id[:db.part/user]
                    :item/quantity 25
                    :item/part [:part/name “partname"]}]


how can i glue that together with transaction [[:assertWithRetracts 17592186045431 :basket/items []]] like that?


two separate calls or is there a way to wire the two together?


ah, i think i can just put both into a transact vector and it will run in one transaction?


@lellis i am struggling wityh how to connect the two. I need the eid of a basket to match a thing created or retrieved by first transaction. the lookup ref will not work in the same transaction (per docs) and i am unsure if they nest anyway. temp id maybe?


       :db/id #db/id[:db.part/user -1]
       ;notice the lookup ref usage to obtain references. Lovely.
       :basket/owner [:user/email “"]
[:assertWithRetracts #db/id[:db.part/user -1] :basket/items []]



i would like that transaction data to tie in nicely, regardless whether the basket just got created or it was there already, but it seems to not work ;/


U want create and retract data in same transact right? @karol.adamiec ?


Is there something I can read to better understand query caching and how to optimize queries?


has some information about both topics


it's not a ton of info, but it has the basics


@lellis well i want to create basket entity or get ahold of it if exists. that entity has a collection of items that need to be reset, thet is why i need the custom dbfn. Default behaviour for cardinality many is adding stuff in. I need to replace the items collection instead.


@geoffs: Thanks! Yeah, I'm aware of clause order and reducing the result set upfront.


What's the most efficient way to retrieve the most recent transaction id for a given entity?


If I have the entity id.


d/datoms with :eavt?






Feels like definitely not d/history.