I want to create a knowledge management system, illustrated by the following example.
Violet nodes are classes. Green nodes are instances.
Red arrows are subclass relationships. Gray arrows are instance relationships.
Blue arrows are questions. Green arrows are answers.
(The direction of Q&A does not really matter.)
The main point is, that a node inherits the questions and answers from all its ancestors.
So in the GUI view of a node, all Q&A pairs will be shown, as well as all unanswered questions.
The following code is my first attempt to model this. The names are the only thing that identifies the questions, and also the only thing that connects Q&A. This feels wrong to me. (Eventually I would use IDs instead of names, but that does not seem much better.)
// class nodes
CREATE (City:Class {name:'city'})
CREATE (Country:Class {name:'country'})
CREATE (Sea:Class {name:'sea'})
CREATE (PortCity:Class {name:'port city'})
CREATE (FrenchPortCity:Class {name:'French port city'})
// instance nodes
CREATE (LaRochelle:Thing {name:'La Rochelle'})
CREATE (Marseille:Thing {name:'Marseille'})
CREATE (France:Thing {name:'France'})
CREATE (Atlantic:Thing {name:'Atlantic'})
CREATE (Mediterranean:Thing {name:'Mediterranean'})
CREATE
// subclass relations
(PortCity) -[:SUB]-> (City),
(FrenchPortCity) -[:SUB]-> (PortCity),
// instance relations
(LaRochelle) -[:INST]-> (FrenchPortCity),
(Marseille) -[:INST]-> (FrenchPortCity),
(France) -[:INST]-> (Country),
(Atlantic) -[:INST]-> (Sea),
(Mediterranean) -[:INST]-> (Sea),
// questions
(City) -[:QUEST {name: 'city part of country'}]-> (Country),
(Country) -[:QUEST {name: 'country access to sea'}]-> (Sea),
(Country) -[:QUEST {name: 'country borders country'}]-> (Country),
(PortCity) -[:QUEST {name: 'port city access to sea'}]-> (Sea),
// answers
(FrenchPortCity) -[:ANS {quest: 'city part of country'}]-> (France),
(LaRochelle) -[:ANS {quest: 'port city access to sea'}]-> (Atlantic),
(Marseille) -[:ANS {quest: 'port city access to sea'}]-> (Mediterranean),
(France) -[:ANS {quest: 'country access to sea'}]-> (Atlantic),
(France) -[:ANS {quest: 'country access to sea'}]-> (Mediterranean);
The following queries can be used to find all the questions and answers for Marseille:
(Only classes can ask questions. Typically instances answer questions. But classes can too.)
This finds the ancestors, i.e. "French port city", "port city" and "city".
MATCH
(thing:Thing {name: 'Marseille'})
-[:INST]->
(parent:Class)
-[:SUB*0..]->
(ancestor:Class)
RETURN ancestor;
And these are the connected questions:
MATCH
(thing:Thing {name: 'Marseille'})
-[:INST]->
(parent:Class)
-[:SUB*0..]->
(ancestor:Class)
-[quest:QUEST]-
(:Class)
RETURN quest.name;
╒═════════════════════════╕
│quest.name │
╞═════════════════════════╡
│"port city access to sea"│
├─────────────────────────┤
│"city part of country" │
└─────────────────────────┘
This finds the ancestors, and Marseille itself:
MATCH
(thing:Thing {name: 'Marseille'})
-[:INST*0..1]->
(selfOrParent)
-[:SUB*0..]->
(selfOrAncestor)
RETURN selfOrAncestor;
And these are the connected answers:
MATCH
(thing:Thing {name: 'Marseille'})
-[:INST*0..1]->
(selfOrParent)
-[:SUB*0..]->
(selfOrAncestor)
-[ans:ANS]-
(ansThing:Thing)
RETURN ans.quest, ansThing.name;
╒═════════════════════════╤═══════════════╕
│ans.quest │ansThing.name │
╞═════════════════════════╪═══════════════╡
│"port city access to sea"│"Mediterranean"│
├─────────────────────────┼───────────────┤
│"city part of country" │"France" │
└─────────────────────────┴───────────────┘
So I have a list of questions and a list of answers, and only need to compare them to find unanswered questions. (In this case none.)
This works. It just does not feel right. I would prefer a more "official" link between Q&A.
I read about the possibility to reify relationships into nodes.
That would allow a real relationship between Q&A.
Is this what you would do?
If there is anything else that comes to your mind, please let me know.