I have a schema with two attributes - :ent/uuid :db.unique/identity
and :ent/context :db.type/ref
- is there a way I can make this automatically create the referenced entity?
(d/transact datomic
[{:ent/context [:ent/uuid (d/squuid)]}])
(obviously this is a contrived example, the (d/squuid)
would almost always be a uuid from somewhere else)(ideally, there's a schema attribute that can set this as a property of :ent/uuid
- but I suspect I'll have to actually go lookup and create the entity if it doesn't exist?)
hmm
(d/transact datomic
[{:ent/uuid #uuid "093eaee6-ebc7-45f2-9a3f-b923f4864e5c"}
{:ent/user [:ent/uuid #uuid "093eaee6-ebc7-45f2-9a3f-b923f4864e5c"]}])
doesn't work? that's a shame - am I looking at this wrong, or do I pretty much have to resort to lookup+tempid's?(for context, I'm wanting to write my code for adaptive gradual backfill of existing entities with uuid's from other databases - as opposed to a dedicated ETL process)
if i'm reading this correctly, you want to transact an entity while also transacting a reference to that entity in the same transaction, right?
if so, then you can use temporary ids within the same transaction
(d/transact datomic
[{:ent/uuid #uuid "093eaee6-ebc7-45f2-9a3f-b923f4864e5c"
:db/id "newuser"}
{:ent/user "newuser"}])
ye, that's basically what I'm doing as a workaround (using d/tempid
) - trouble is that you have to actually have to think about it, at a higher level
where I would have preferred to just (effectively):
(->>
[(when user-not-found {:ent/uuid #uuid "093eaee6-ebc7-45f2-9a3f-b923f4864e5c"})
{:ent/user [:ent/uuid #uuid "093eaee6-ebc7-45f2-9a3f-b923f4864e5c"]}]
(remove nil?))
instead, I need to collaborate the two pieces of code to pass the temporary id aroundnot a major problem, but seems a bit odd, given how lovely lookup refs are
> I'm wanting to write my code for adaptive gradual backfill of existing entities with uuid's from other database i do something similar from time to time, and what i do is first transact the entities in the DB, and then in a second transaction i establish their references. you might be able to do something clever, like walk your input data and create a tempid out of the uuid (i never had to go that far)
it's a pain though 😉
ye, I'm trying to whittle down a simple paradigm for consistently interacting with datomic that I can then teach to the team.. save then load would work, but a bit too much of fickle
but thanks 🙂
well if you ever write a generic walker/id replacer for the input code let us know! in my case i migrate slices of the datomic graph from one database to another, and over time i have just added steps for each "kind" of entity. another useful tool would be to replace UUIDs with new ones.. in other words clone parts of the graph and their relationships (within the same db).
just another thought, and i don't know if this applies to your scenario, but you can transact new entities as reference values if the reference is a component
{:tx-data [{:user/id #uuid "093eaee6-ebc7-45f2-9a3f-b923f4864e5c"
:user/address {:address/id #uuid"f0ef5f94-8125-4aa1-a906-524ec0274941"
:address/street "Maple Street"
:address/country-code "US"}}]}
that is good to know, thanks! but no, this is for the generic case, not really components
I guess I could handle a generic walker, but that would add a bunch of overhead for 99% of the code that doesn't need it + be an extra bit of complexity to keep having to think about
so prefer to just shift paradigm a little xD
You can transact the whole thing as a nested map:
[{:ent/user {:ent/uid #uuid "MY_UUID_HERE"}}]
ooh - even without being a component?
and if you do it twice, it just works?
[{:ent/user {:ent/uid #uuid "MY_UUID_HERE"} :ent/ident "1"}
{:ent/user {:ent/uid #uuid "MY_UUID_HERE"} :ent/ident "2"}]
for instancealso - is that infinitely nestable?
sure
very cool - I'll be abusing that, thanks!
https://docs.datomic.com/on-prem/transactions.html#nested-maps-in-transactions
there are a couple of caveats ^
hehe, thanks - I'll have a read 🙂
in particular you need a unique attribute in the inside entity
or it has to be component
cool - ye, I'll be enforcing :ent/uuid
- so that it can always gradually converge to the same entity.. I do have a few more identity
attributes, but there's a possibility of creating two rows for the same entity, then not being able to reconcile later.
yep, you'd need to make sure that was handled when you build the nested map
:thumbsup: thank you!
Does anyone actually uses the schema type :db.type/uri
? There's some real benefit apart from semantics? Using :db.type/string
works just fine and I don't need any code to serialize/deserialize the data.
I have used it. I like that it rejects invalid uris. I also see more types as a bonus.
I don’t think there’s anything wrong with using strings instead
I took this :db.type/tuple
schema example from Datomic’s On-Prem documentation. https://docs.datomic.com/on-prem/schema.html#heterogeneous-tuples
{:db/ident :player/location
:db/valueType :db.type/tuple
:db/tupleTypes [:db.type/long :db.type/long]
:db/cardinality :db.cardinality/one}
But I get this error when running a transact
(with com.datomic/client-pro
“0.9.57” ( also tried “0.9.63" )).
Is this just a bug? Or is there something else to making tuple types work?
Caused by: datomic.impl.Exceptions$IllegalArgumentExceptionInfo: :db.error/not-an-entity Unable to resolve entity: :db/tupleTypes
{:entity :db/tupleTypes, :db/error :db.error/not-an-entity}
Did you upgrade your base schema? https://docs.datomic.com/cloud/operation/howto.html#upgrade-base-schema
Oh, I didn't have that in mind. Thanks! I think I'll use :db.type/uri
because of the free type checking.
I haven’t deployed yet. This is all in development, with this version.
com.datomic/client-pro "0.9.57"
This is all tied to the storage not the client
The db you are connecting to: was it created with a version of datomic earlier than the one that started supporting tuples?
if so, then you need to follow the instructions to upgrade the base schema
upgrading the base schema will transact entities like :db/tupleType
Hmm, right. Probably something with the datomic engine. Ok, cheers.
Has anyone gotten dev-local working on windows 10? I'm having a hard time with specifying {:storage-dir "C:\\Users\user\foo"}
Execution error at datomic.dev-local.impl/user-config (impl.clj:324).
Unsupported escape character: \U
you probably need "C:\\\\Users\\user\\foo" to escape the \'s ?
@alexmiller Different error message, but still doesnt work
what's the error?
Execution error (ExceptionInfo) at datomic.core.anomalies/throw-if-anom (anomalies.clj:94).
You must specify an absolute path under :storage-dir in a map in
your ~/.datomic/dev-local.edn file, or in your call to client.
interesting, it's checking for absolute path - maybe "\\C:\\\\Users\\user\\foo" ?
Same error with that unfortunately
sorry, that extra pair of \\ isn't needed and paths on windows starting with the drive should be considered absolute. "C:\\Users\\user\\foo" I would expect to work, but maybe I'm missing something
Sadly, same error again. Thanks for your help alex!
@jaret yes, that's the last one I tried
Firing up a windows machine to test. Will update here or on the ticket 🙂
Cool, thanks @jaret! this isn't super urgent for me. my main box is debian. my clojure code talks to a game that I'm running on my Windows machine. Going to go forward with ngrok in the mean time.