I would model all relationships in Seed as typed, directed triples, following the RDF model, but with an important distinction between structural, referential, and conversational relationships.
The basic model is:
Subject → Predicate → Object
For example:
Document A → hasChild → Document B
Document B → linksTo → Document C
Comment X → commentsOn → Document B
Document B → hasParent → Document A
However, I would avoid storing both directions of a relationship unless necessary.
1. Three fundamental categories of relationships
I would distinguish three semantic categories:
Category | Predicate | Inverse | Meaning |
Structural | hasChild | hasParent | Document hierarchy |
Referential | linksTo | linkedFrom | Hypertext links |
Conversational | commentsOn | hasComment | Commentary attached to content |
Conversational | repliesTo | hasReply | Conversation threading |
Structural | contains | containedIn | Blocks within documents |
Referential | transcludes | transcludedBy | Content inclusion |
Semantic | references | referencedBy | General reference to an entity |
Semantic | defines | definedBy | Concept definitions |
These relationships have different meanings even though they share the same triple representation.
2. Store canonical relationships, derive inverses
Rather than storing:
A → hasChild → B
B → hasParent → A
I would store only:
B → hasParent → A
Then derive:
A ← hasParent ← B
The same applies to backlinks.
Store:
A → linksTo → B
Query the inverse:
?source → linksTo → B
This is particularly important in a distributed system: you don’t want two independently maintained facts that could become inconsistent.
An inverse relationship is a different way of querying the same fact, not necessarily another fact.
3. Distinguish structural relationships from hyperlinks
Consider three documents:
Document A: Knowledge Graphs
├── Document B: RDF
└── Document C: Ontologies
The triples could be:
B → parent → A
C → parent → A
B → linksTo → C
These represent fundamentally different relationships.
Parent establishes a structural relationship in a document hierarchy.
LinksTo establishes a hypertext reference without changing document structure.
A document could also have multiple parents if Seed supports multiple structural contexts. That would make the structure a directed graph rather than a strict tree.
4. Model commentary as a first-class object
For Seed, I would treat comments as objects with their own identities.
For example:
Comment X → commentsOn → Document A
Comment X → createdBy → Alice
Comment X → repliesTo → Comment Y
But Seed supports fragment-level commentary, so the target may be more specific:
Comment X → commentsOn → Block B
Or even:
Comment X → commentsOn → Fragment F
Fragment F → partOf → Block B
Block B → partOf → Document A
This allows comments to participate in the same graph as documents, blocks, and links.
5. Should links themselves be objects?
This is an important architectural decision for Seed.
A simple triple:
A → linksTo → B
works when the relationship needs no additional properties.
But suppose a link has:
An author
A creation timestamp
A specific source fragment
A specific target fragment
A version or causal history
An annotation
Then you might want to give the link its own identity.
For example:
Link L → source → Document A
Link L → target → Document B
Link L → type → Hyperlink
Link L → createdBy → Alice
This is similar to RDF reification or property graphs with edge properties.
An alternative is RDF-star, which allows statements about triples:
<< :A :linksTo :B >> :createdBy :Alice .
However, if a link is a persistent, independently addressable distributed object, I would favor an explicit link identity.
6. My proposed minimal vocabulary for Seed
I would start with a relatively small vocabulary:
Predicate | Purpose |
parent | Structural hierarchy between documents |
contains | Structural containment of blocks |
linksTo | Explicit hypertext links |
transcludes | Inclusion of external content |
commentsOn | Commentary targeting content |
repliesTo | Conversation threading |
references | General semantic reference |
defines | Definition of a concept |
instanceOf | Classification of an object |
I would not introduce backlinks, children, hasComments, or hasReplies as separately stored predicates. These are inverse views of canonical relationships.
You can expose them in the UI without storing redundant facts.
7. One important distinction: ownership vs relationships
For a distributed hypermedia system, there is another consideration.
Suppose:
Comment X → commentsOn → Document A
Does this mean Document A owns Comment X?
No.
It only establishes a relationship between two independently identified objects.
Similarly:
Document B → parent → Document A
does not necessarily mean A owns B, controls its permissions, or determines its lifecycle.
This separation is essential for Seed’s distributed object model.
You could distinguish:
Identity: What object is this?
Structure: Where does it appear?
Reference: What does it point to?
Authority: Who can modify it?
Provenance: Who asserted the relationship?
These are separate dimensions.
8. One architectural recommendation
I would represent relationships internally as:
type Triple = {
subject: ObjectID
predicate: PredicateID
object: ObjectID
}
And expose a graph query interface supporting both directions:
graph.outgoing(documentA, "linksTo")
graph.incoming(documentA, "linksTo")
graph.outgoing(documentB, "parent")
graph.incoming(documentA, "parent")
For distributed assertions, you would additionally need provenance and versioning metadata, either on the assertion or through its containing signed change.
A question worth resolving
Are you trying to model the relationships between objects, or are you trying to model all relationships as first-class objects themselves?
These lead to two different architectures:
A. Triple-based graph: Relationships are facts connecting objects.
B. Distributed object graph: Relationships can themselves have identities, authors, versions, permissions, and histories.
Given Seed’s ambitions around persistent identity, distributed objects, and traceability, I would lean toward B for relationships that need independent identity, while keeping ordinary structural and referential facts as simple triples.
Do you like what you are reading? Subscribe to receive updates.
Unsubscribe anytime