This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-08-09
Channels
- # aleph (21)
- # architecture (5)
- # boot (25)
- # cider (1)
- # cljs-dev (115)
- # clojure (59)
- # clojure-brasil (3)
- # clojure-dev (4)
- # clojure-italy (20)
- # clojure-nl (2)
- # clojure-portugal (6)
- # clojure-russia (12)
- # clojure-spec (43)
- # clojure-uk (37)
- # clojurescript (76)
- # datomic (123)
- # emacs (3)
- # graphql (2)
- # hoplon (5)
- # jobs-discuss (1)
- # jobs-rus (4)
- # keechma (7)
- # lein-figwheel (13)
- # leiningen (7)
- # lumo (2)
- # off-topic (17)
- # om (6)
- # onyx (26)
- # parinfer (19)
- # planck (2)
- # re-frame (80)
- # reagent (9)
- # ring (1)
- # spacemacs (45)
- # testing (1)
- # vim (28)
hi, i have a modeling question. We’re kicking off a new project and one of the first things is coming up with a schema for people, orgs, etc. This is traditionally done with something like Parties and Roles. It makes sense logically, but most of the practical guidance is based on shoehorning that into a relational model. just wondering about doing it in a more “Datomicy” manner. I was thinking for something like Person (Party) and Customer (Role), that I’d have a person entity (:person/fname, :person/lname, etc) that refs a set of roles where one might be Customer (:customer/shippingaddress, etc)
@eoliphant I am completely new to Datomic but I am working on my first project and had to think about a similar modeling question so I can share with you my approach (which might be flawed, who knows…)
Roughly speaking, persons in my system are represented as “identities”, and roles as “facets”. An identity in my system can have a number of facets (administrator, coordinator, and a few others in my case)
sure 😉 I’ve been using it a bit now for small services, so we haven’t hit many major modeling issues. Now we’re starting to attack the core domain so the now the fun begins
Initially I modelled it as a :identity/facets
attribute with cardinality many, but ended up moving to an attrbute per facet, e.g. :identity/administrator-facet
, each of which may be null (I found it a bit easier to work with in my project)
Although in my project those “facets” are not just roles for access control, they are more like “profiles”, used both for access control and to store profile-specific attributes
ours is even more fun. As you may have varying ‘facets’ that provide context for your relationship with other persons/organizations.
‘roles’ in this context aren’t necessary atuhorization roles (though they may guide allocating them, etc)
Mmh that sounds a bit similar to mine. My users might have multiple facets, with various attributes
No worries. Please share if you have any striking insights on how to deal with this stuff 🙂
Yeah 😄 I feel it’s very natural to think in terms of graphs when working with Datomic
yeah it’s far more natural in most cases, it’s just decades of ‘thinking in tables’ lol
I did some stuff with RaimaDB like two decades ago that was much closer to the way datomic works
As I said I am new to Datomic, and one of the things hurting my brain at the moment is the amount of discipline you need to model data properly
@eoliphant if you namespace your attributes, then you don't need to treat it as inheritance
e.g. any entity w/ :customer/shipping-address
works as a customer
but that’s a pretty simplistic example for us, i’m trying to balance the flexibility of just dumping attrs on an entity and keeping the model relatively robust. I guess in object terms, what I was thinking was more composition than inheritance?
i think the main issue is that ‘you’ as a ‘person (Party) may assume certain roles in relation to other Parties
I think this is outside the scope of the db - the point of datomic is using the database to store data
So that’s where I’ve been wondering if the breakout of the role specifc stuff onto another entity might be in order
queries are straightforward. e.g. a query like [?p :person/id ?some-id] [?p :customer/shipping-address]
will return an empty set
but the entity for that :person/id
may valid in another context (not shipping someting)
but this is different than querying like [?p :person/role :person.role/customer]
or something like that
yeah and I’ve got some stuff along those lines. I think customer might have been a bad example lol, as it’s actually straightforward to model it’s just that in this domain you might be a ‘customer’ with varying attributes depending on certain relationships
what I was saying that you might have :person/roles
pointing to a ref of type customer, with additional data on it
can two entities point to the same customer ref?
also, can you have a customer without a person? does that make sense?
I think you're trying to model tables on top of datomic w/ refs
if all this data is about the same "thing", they share an entity
so just use attributes
another way to think about it is: you store facts, and queries project these facts into tables
yes good point. I’ve done some other small greenfield projects and didn’t have too much of an issue with modeling around facts
so kind of have to ‘unsee’ aspects of the current approach to get this right i think
@hcarvalhoaves are you sure it is reasonable to store everything that is about the same “thing” under one entity? It seems problematic, particularly if you have a one-to-many relationship, where the many things could be considered to be a part of the “thing”
you can’t really model that with attributes on a single entity; refs seem to make sense
if you have a one-to-many relationship
<- then you don't have one entity anymore
well, under your definition, I could (if I understand it correctly). The “many” pieces might not have an existence of their own (aka the answer to the question “can you have one of these without X?” would be no, where X is your “main” entity)
e.g. in his case person
and customer
are just facets of the same entity - 1:1
right, but you could easily conceive a case where person has many “administrator” facets for different groups, or similar
can you give a concrete case?
not really, because the only case I have in mind could be solved without having multiple facets of the same kind
well, going back to eoliphant's example
it boils down to this: if I assert entity e1 has :customer/shipping-address
, does it matter what customer
is?
e.g. I could have :shipping/address
the notion of customer
doesn't exist at the data level - it's in your application
the only thing at the data level is that e1 has this new fact about it
now, maybe it makes sense to assert that, at some point, this entity is now a customer. there are a few possibilities
usually, turning into a customer means there will be unique fact you want to assert, e.g. :customer/ssn
and then you can infer it started being a customer at the time of this transaction
(and if you retract those attributes, it stops working as a customer)
otherwise, usually you'll have a synthetic attribute like :customer/id
either way, you have a way to distinguish what works as a customer or not in a query
I just don't know if the notion of "customer" matters much e.g. an entity can have many :customer/*
attributes but without :customer/shipping-address
, this "customer" doesn't exist for logistics
to get more philosophical here: in real life, is common to see many different interpretations of "is a", depending on who is consuming the data
@hcarvalhoaves thanks, that’s very insightful. Bouncing off a small detail in your explanation: would you then have multiple “ids” attached to an entity, one for each of its “facets”? e.g. :person/id
, :cuztomer/id
, etc
IMO it's fine, it's just another unique attr
you talked about a problem I encountered in my project: I have a facet which has no attributes, so I need some “witness attribute” to know an entity has this facet
the reason you usually need those ids
is because entitiy ids are internal to datomic - you don't want to expose those