datascript

2024-05-16T17:14:03.365659Z

I have need to put UUIDs (as strings) on more or less every entity in my DataScript DB. they'll either be supplied by upstream data getting ingested into DataScript (easy enough) or for newly minted entities will get generated locally and included. I'd be happy to use the UUID strings as entity IDs straight in DataScript but I https://github.com/tonsky/datascript/issues/168 that it's not currently possible to do that. (I don't care about storage, if that makes a difference.) is there a way to auto-fill these at transaction time? I often transact big complicated maps with a mix of upserts and new entities nested all inside them, so it's not practical to know where all the new entities are. I can do (d/q '[:find ?e :in $ :where [?e _ _] [(missing $ ?e :my.ns/uuid)]] db) after each transaction, I suppose.

Filipe Silva 2024-05-30T13:23:52.468659Z

What's the case where you're not sure if you should add a new uuid though? It sounds like you either have it provided from your data source, or you should add one.

2024-05-30T13:25:21.658099Z

It's that I'm sometimes not so clear in my code to build transactions whether this is an update or a new value.

2024-05-30T13:26:01.911929Z

I ended up putting in the necessary conditions by hand. I'm not thrilled about that, but there's not really a good alternative, and the set of functions adding and updating things is limited.

Filipe Silva 2024-05-30T13:26:24.987249Z

If you make the uuid unique on the schema, the entity will be up setter

Filipe Silva 2024-05-30T13:26:40.533969Z

Upsertted

Filipe Silva 2024-05-30T13:27:27.867549Z

So you can just transact your nested objects with uids in them directly: if the entity exists it will be a upsert, if it doesn't exist it will be an insert

Filipe Silva 2024-05-30T13:52:56.251949Z

(require '[datascript.core :as d])
;; :db/ident is already unique
(def schema {:children {:db/cardinality :db.cardinality/many
                        :db/valueType   :db.type/ref}})
(def conn (d/create-conn schema))

(d/transact! conn [{:db/ident "uuid1"
                    :prop1 1}])
(d/touch (d/entity @conn [:db/ident "uuid1"]))
;; => {:prop1 1, :db/ident "uuid1", :db/id 1}

(d/transact! conn [{:db/ident "uuid1"
                    :prop2 2}])
(d/touch (d/entity @conn [:db/ident "uuid1"]))
;; => {:prop1 1, :prop2 2, :db/ident "uuid1", :db/id 1}


(d/transact! conn [{:db/ident "uuid1"
                    :children [{:db/ident "uuid2"
                                :prop1 1}
                               {:db/ident "uuid3"
                                :prop2 2}]}])
(d/touch (d/entity @conn [:db/ident "uuid1"]))
;; => {:children #{#:db{:id 2} #:db{:id 3}}, :prop1 1, :prop2 2, :db/ident "uuid1", :db/id 1}

(d/touch (d/entity @conn [:db/ident "uuid2"]))
;; => {:prop1 1, :db/ident "uuid2", :db/id 2}

(d/touch (d/entity @conn [:db/ident "uuid3"]))
;; => {:prop2 2, :db/ident "uuid3", :db/id 3}

Filipe Silva 2024-05-30T13:53:43.075899Z

I used to do this with a custom :block/uid prop but I've since learned that :db/ident seems to already be unique

Filipe Silva 2024-05-30T13:54:16.234149Z

you can also query directly for the unique prop with the ref lookup [:db/ident "whatever"] on pull/entity/etc

2024-05-30T14:16:17.352519Z

yes, I'm familiar with that approach. it's working well, I was just wondering if there was a slick way to hook in to attach a UUID to every entity, or nearly every entity. it's working fine, so no worries now.

Niki 2024-05-16T19:29:34.104099Z

You can totally store uuids, either as strings or as uuid type, just store them as an attributte

2024-05-16T19:31:27.261199Z

is there a slicker way to enforce them than editing all the code that inserts new entities, and adding a post-test fixture that checks for anything without one?

Niki 2024-05-16T19:31:59.767219Z

no, I don’t think so

2024-05-16T19:32:37.370889Z

fair enough. thanks!

Sam Ferrell 2024-05-16T20:27:44.519379Z

ive definitely had this need and i think niki talked about using uuids in a hypothetical datascript 2 https://tonsky.me/blog/datascript-2/

Sam Ferrell 2024-05-16T20:28:06.396419Z

but yeah i just added them manually in all my transaction fns