(another) Generic query/structure-advice question: Among other things, I'm trying to model some relationships between entities in my database, some of them are one-directional (like parent->child), others are bi-directional (like sibling->sibling) (both are modeled the same way). As I understand, I have two main options for modeling relationships: 1) Relationship-as-attribute: directly connecting the entities
[?a :family/child ?b]
2) Treating relationships as a separate entity
[?r :relationship/type :child]
[?r :relationship/from ?a]
[?r :relationship/to ?b]
I'm currently using Option 2, based on this conversation here wrt normalization (considering that a number of these relationships would be cardinality-many) https://clojurians.slack.com/archives/C01RD3AF336/p1772225568874479
Question 1: Does that sound reasonable, or do you think this style of normalization will cause me pain?
I currently am not enforcing a 'full net' for sibling->sibling relationships in the DB, meaning, A -> B and B -> C relationships do not also require A -> C to be present, but a (siblings-of A) query should return both B and C.
Question 2: Does that sound reasonable? I assume it depends on how high I may expect sibling-counts to get (a full net of 100 siblings is a lot of relationships, 3 is much more reasonable)? My current approach however will require more work on queries to find transitive siblings. Is there a better option?
I'm trying to think of how to actually do that transitive siblings query with my current set-up, all my approaches feel a little hairy so far, and I'm wondering if that difficulty is from my unfamiliarity with querying, or from a flawed db design.Your data is surely totally different from mine. When the sibling relationship does not need its own attributes you might not need to have it in your model at all. Siblings is children of my parents (minus self). This can yield a simple, lightning fast pull even with thousands of sibling.
These are two independent questions. For question 1, as you have correctly identified, if you have many-to-many relationship, a relationship entity is a better option.
For question 2, how to implement transitive closure. The standard answer is to use recursive rules. Any difficulty you had is perhaps due to not using recursive rules, nothing to do with db schema.
One of the main powers of Datalog lies in the recursive rules. Not using rules missed out half of Datalog.
BTW, all these, will be discussed in the upcoming book.
I am so eagerly awaiting that book 😄 And I'm certainly not properly using rules yet, I saw some mentions of it as I was looking up other opinions, but i wasn't confident in copying advice from datomic forums considering most of their examples where with cardinality-many attributes, good to know rules are still the route to go, I'll need to practice :^)
cardinality-many attributes work the same way in Datalevin.
right right, i just mean that most examples i saw weren't using a separate relationship entity