Fork me on GitHub
#datascript
<
2021-10-02
>
zeitstein12:10:44

Looking for help modelling the following. I want to associate, to a single entity, multiple property-reference, value-of-property pairs. The property should be an entity itself (linking its name, type, possible enumerated values, etc). 1. I could do this via cardinality/many heterogenous tuples in Datomic, but afaik DataScript doesn't support this. Neither tuples like [:db.type/ref :db.type/string] nor having an attribute of tuples with cardinality/many. 2. I could create an intermediate entity playing the same role as the tuples above (i.e. having two attributes: a ref and a string). But this seems somewhat wasteful. 3. Instead of pairs, I could associate to each entity a value-of-property entity. Then this entity could link to appropriate property. But, as above, this would require storing an entity for each value (which seems conceptually crazy as well. EDIT: when the value is not enumerated). 4. I could use 'dynamic' attributes such as :entity.property/property-name which would link the entity and value-of-property. This would require parsing the keyword to get property-name and then query for the corresponding property... among other complications. Am I missing something? If not, which option should I go with? Thanks!

refset13:10:35

For option (1) are you hitting comparison errors? If using ClojureScript here (not Clojure), I've had good success messing around with (extend-protocol IComparable ...) before, as per suggestions in this thread https://github.com/tonsky/datascript/issues/69#issuecomment-128738917

refset13:10:42

In my case I created a new kind of record, which is essentially just a regular map, that I could then store easily and do arbitrary things with: > (defrecord Smap [m]) > (extend-protocol IComparable Smap (^number -compare [x y] 0)) > > (Smap. {:foo "bar"}) ;; this map can be transacted into datascript as a value See also https://github.com/tonsky/datascript/issues/383

zeitstein14:10:54

Thanks, but no comparisons, simply trying to model my domain as I'm learning Datomic/DataScript. Working from Clojure REPL. The DataScript issue in 1) has been raised https://github.com/tonsky/datascript/issues/364.

refset15:10:24

Ah okay, well DataScript may not yet provide "native" support for resolving/managing the such :db.type/ref values, but you can certainly still manually store multiple (cardinality-many) vectors containing the internal entity IDs (i.e. userspace refs). And if/when that feature does arrive, I expect the migration should be easy enough.

zeitstein16:10:55

Should I take this to mean you would recommend going with option 1)? Even though it means more manual work, compared to options 2) or 3).

refset17:10:36

Well, I'm just a passer-by (and very-occasional project contributor 🙂) who hasn't ever deployed DataScript into prod...but yeah, to me (1) seems nicest. I think if there's any chance that you might need this pattern again then the one-time manual work for (1) is worth it, as it keeps the schema small and the indexes fast.

zeitstein17:10:32

Thanks for your help!

🙏 1
John Conti21:10:19

I am interested in the paths not taken here. #2 and #3. What is the downside to regarding these special values as entities? This pattern has always suited me when I wanted to be able to find all the properties with a special enumerated value? Likewise to find all the domain entities with a particular property, having the property be an entity was useful. I get the idea there may be performance penalties? Or maybe just other cross-cutting concerns in the code I cannot imagine?

zeitstein05:10:19

Datomic does https://docs.datomic.com/on-prem/schema/schema-modeling.html#enums modelling enumerated values as entities; DataScript has https://github.com/tonsky/datascript/wiki/Tips-&amp;-tricks. In my case, some properties wouldn't have enumerated values. Storing simple scalar values as entities (especially when I would have many), seems wrong to me. I've been trying to handle both types of values in a similar fashion, but perhaps I shouldn't.