This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2024-03-17
Channels
Can :db/ident
be used to declare enumerated values?
Documentation for a certain product says, "... :db/ident
... [may] be used ... to represent enumerated values." Datascript's "Differences from Datomic" says "No :db/ident
attributes". Datalevin's "Differences from Datascript" does not mention :db/ident
. On the other hand, datalevin's test/datalevin/test/transact.clj appears to assign ident :Petr
.
There is no special status for :db/ident
, it is just a keyword valued attribute that is marked as unique, same as other such attributes. There's indeed logic to check for them in entity resolution, but that's after checking lookup ref, so it's not a shortcut either.
That test is from datascript, probably for compatibility with datomic. So yes, you can use :db/ident
for enumerated values purpose and we do support it, but it's nothing special and there's no special advantage for doing so, compared with defining your own unique identity attribute and using lookup ref.
pull
(https://cljdoc.org/d/datalevin/datalevin/0.9.3/api/datalevin.core#pull) says, "Supported opts: :visitor
a fn of 4 arguments, will be called for every entity/attribute pull touches..." What is the role of the visitor function, or, what should it return and can it affect the outcome of the pull
?
The role of visitor is to have side effect, it should return nil, or more precisely, whatever it returns is ignored. It does not affect the outcome of pull
.
It looks like with-conn
evaluates its spec argument 4 times, which is harmless if it is a literal but could cause a surprise if it calls a function with cost or side effects. https://github.com/juji-io/datalevin/blob/0.9.3/src/datalevin/core.clj#L961
(I was puzzled how get-conn
and with-conn
use the schema if the connection already exists, so I clicked the link to source, which is a very nice feature.)
Hi, I am just checking the recent commits in Datalevin and I am in a bit of trouble figuring out this potential bug in 0.9.3.
My understanding is that since with-conn
is a macro, spec
is passed as a form and is destructured during macro evaluation into distinct let bindings, and so it looks perfectly safe to me.
Could you please show me an example where the old code could actually lead to multiple evaluations?
You are right @U2E1D7WUB. Oops!
No. The same DB file can have both. Datalog DBIs are not special. A db file can have 128 DBIs by default. The DBIs are searched sequentially by name through, so you don’t want too many of them. You can pass an option to change it
Datalog uses 6 DBIs, if full text is enabled, the default search engine uses up to 4. But each search domain use that many too.
What db/valueType is recommended for an enumerated type? For example, if attribute :e/x will hold one of (a,b,c), and a jillion entities will have attribute :e/x, is it recommended to store :e/x as :a,:b,:c ; or "a", "b", "c" ; or 1, 2, 3 with a distinct mapping, outside the datalevin database, to make sense of those numbers?
Also, using :db/ident
is not required to solve this problem. It's a convenience mechanism that Datomic introduced to have an additional keyword identifier for an entity. In datalevin, it is implemented as the same as other attributes that are marked as unique identity, i.e. it is not special. Because in our storage layer, keywords are more expensive than strings with the same name, I would just use a string instead and use lookup ref for the entity. Of course, if one likes the neatness of using a keyword to stand for an entity, :db/ident
is for you. Performance wise, I have not compared the two formally, but I doubt this makes a huge difference. To disambiguate, one probably wants a long namespaced keyword for a :db/ident
but one doesn't need to do this for a string valued unique custom attribute. So I personally would favor the later. In any case, it's a matter of personal preference.