Annotated relationships in Datomic
I was hoping to extend the conversation on this SO question and get some more details in terms of implementation.
My requirements include allowing an admin to define tags on a relationship, the number of which is arbitrary, the entities involved are arbitrary, and the entities involved are not contingent (ie not a Component
of the entity).
For a contrived example, a User
can have many Projects
. A Project
can have many Users
.
The admin creates an arbitrary number of tags to assign to related Users per relationship eg Owner
, Contributor
, VIP
, etc. for User
to Project
.
From what I understand of this answer, a simple ref
is insufficient and I will need to create an additional entity, something like this-
Pertinent Project
attribute
:db/ident :project/associations
:db/valueType :db.type/ref
:db/cardinality :db.cardinality/many
Pertinent User
attribute
:db/ident :user/associations
:db/valueType :db.type/ref
:db/cardinality :db.cardinality/many
Pertinent Association
attributes
:db/ident :association/related-ents
:db/valueType :db.type/string
:db/cardinality :db.cardinality/many
:db/ident :association/assoc-id
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db/ident :association/tag
:db/valueType :db.type/ref
:db/cardinality :db.cardinality/one
Pertinent Tag
attribute
:db/ident :tag/name
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
This is as far as I have gotten. I am not clear as to how to construct the association
entity in an idiomatic-Datomic way.
To find associated relationships on a given Project
, including but not limited to Users
, as well as find relationships where relationship tag = Contributor
, should I
1) Drop the refs
on Project
+ User
and retrieve the data via Associations
? ie return all Associations where association/related-ents
contains User-Id = foo
2) Something entirely different.
I suppose my question boils down to where do I store the ref
for efficient look-ups? Is there a different db.type
that should be used instead of string
, or a different construct for the association
that is needed? Are the project/associations
and user/associations
refs
even necessary?
Appreciate any insight.
Update
After a bit more reflection, I think I tripped up on the refs
on the various entities. I am wondering if I could simply have an associations/relatedEnts
that is itself a ref that holds 2 Datomic db ids + tag and drop all of the other listed attrs. Is this ideal?
:db/ident :association/relatedEnts
:db/valueType :db.type/ref
:db/cardinality :db.cardinality/many
:db/ident :association/tag
:db/valueType :db.type/ref
:db/cardinality :db.cardinality/one
When you're defining an entity to represent the relationship between two other entities (a User
and a Project
in your example), I'd recommend making the linkage from that reified relationship entity (your Association
) to the other entities via Datomic references. This preserves the ability to navigate from one to the other without having to, for example, parse a compound string.
Additionally, your example suggests to me that you're considering only having a single Association
entity to represent the relationship(s) between many Users
and Projects
. Although this approach can work, you will have much greater flexibility and potential for customization if you create an Association
entity for every relationship you're modeling. If you prefer to think of this as a graph-modeling problem, your User
and Project
entities are nodes of the graph and you create an 'edge entity' for each edge between two nodes. Each of those 'edge entites' is represented by an instance of an Association
that has two reference attributes, one to the User
and one to the Project
. Then that Association
can also have as many arbitrary additional attributes as you want, allowing you to attach data directly to the relationship (ie for your tag attributes, or any other data you want to represent about the relationship).
Best, Marshall
链接地址: http://www.djcxy.com/p/65270.html上一篇: 与“重置”操作有很多关系
下一篇: 在Datomic中注释的关系