如何在图形数据库中建立真实世界的关系(如Neo4j)?
我有一个关于在图形数据库中建模的一般问题,我似乎无法将我的头围绕。如何在图形数据库中建立真实世界的关系(如Neo4j)?
你如何塑造这种类型的关系:“牛顿发明微积分”?
在simple graph,你可以喜欢这个型号:
Newton (node) -> invented (relationship) -> Calculus (node)
...所以你有一堆,你增加了更多的人,发明的“发明”曲线关系。
的问题是,你开始需要一堆属性添加到关系:
- invention_date
- influential_concepts
- influential_people
- books_inventor_wrote
...和您需要开始在这些属性和其他节点之间创建关系,如:
- influential_people:对人的关系节点
- books_inventor_wrote:关系到预定节点
所以现在看起来像“真实世界的关系”(“发明”)实际上应该是一个节点图形,图形应该是这样的:
Newton (node) -> (relationship) -> Invention of Calculus (node) -> (relationship) -> Calculus (node)
而对于复杂的事情更多,其他人也参加微积分的发明,使图表现在变成这样的:
Newton (node) ->
(relationship) ->
Newton's Calculus Invention (node) ->
(relationship) ->
Invention of Calculus (node) ->
(relationship) ->
Calculus (node)
Leibniz (node) ->
(relationship) ->
Leibniz's Calculus Invention (node) ->
(relationship) ->
Invention of Calculus (node) ->
(relationship) ->
Calculus (node)
所以我问这个问题,因为它看起来像你不想实际的图形数据库上设置属性“的关系”对象,因为你可能想在某个点将它们视为图中的节点。
这是正确的吗?
我一直在研究Freebase Metaweb Architecture,他们似乎把所有东西当作一个节点。例如,Freebase的想法是Mediator/CVT,您可以在其中创建一个将“Actor”节点链接到“Film”节点的“Performance”节点,如下所示:http://www.freebase.com/edit/topic/en/the_last_samurai。不太确定这是否是同一个问题。
你有什么指导原则可以用来确定“现实世界关系”是否应该实际上是一个图节点而不是一个图关系?
如果有关于这个话题的好书,我很想知道。谢谢!
其中一些东西,如invention_date
,可以存储为边上的属性,就像在大多数图形数据库中一样,边可以具有与顶点可以具有属性相同的属性。例如,你可以做这样的事情(代码如下TinkerPop's Blueprints):
Graph graph = new Neo4jGraph("/tmp/my_graph");
Vertex newton = graph.addVertex(null);
newton.setProperty("given_name", "Isaac");
newton.setProperty("surname", "Newton");
newton.setProperty("birth_year", 1643); // use Gregorian dates...
newton.setProperty("type", "PERSON");
Vertex calculus = graph.addVertex(null);
calculus.setProperty("type", "KNOWLEDGE");
Edge newton_calculus = graph.addEdge(null, newton, calculus, "DISCOVERED");
newton_calculus.setProperty("year", 1666);
现在,让我们展开它一点点,并添加Liebniz:
Vertex liebniz = graph.addVertex(null);
liebniz.setProperty("given_name", "Gottfried");
liebniz.setProperty("surnam", "Liebniz");
liebniz.setProperty("birth_year", "1646");
liebniz.setProperty("type", "PERSON");
Edge liebniz_calculus = graph.addEdge(null, liebniz, calculus, "DISCOVERED");
liebniz_calculus.setProperty("year", 1674);
添加在书:
Vertex principia = graph.addVertex(null);
principia.setProperty("title", "Philosophiæ Naturalis Principia Mathematica");
principia.setProperty("year_first_published", 1687);
Edge newton_principia = graph.addEdge(null, newton, principia, "AUTHOR");
Edge principia_calculus = graph.addEdge(null, principia, calculus, "SUBJECT");
要找出牛顿在他发现的东西上写的所有书籍,我们可以构造一个图遍历。我们从牛顿开始,遵循他发现的事物的链接,然后反向链接获取有关该主题的书籍,并再次通过链接反向获取作者。如果作者是牛顿,那么回到书中并返回结果。该查询是写在Gremlin,为图遍历一个基于Groovy领域特定语言:
newton.out("DISCOVERED").in("SUBJECT").as("book").in("AUTHOR").filter{it == newton}.back("book").title.unique()
因此,我希望我已经证明了一点聪明的遍历如何使用,以避免产生中间节点代表问题边缘。在一个小型的数据库中它并不重要,但是在一个大型数据库中,你将会遇到大量的性能问题。
是的,很遗憾,您不能将边与图中的其他边相关联,但这是这些数据库的数据结构的限制。有时将所有内容都作为节点是有意义的,例如,在Mediator/CVT中,性能也具有更具体一些。个人可能只希望在评论中提到汤姆克鲁斯在“最后的武士”中的表现。但是,对于大多数图形数据库,我发现某些图遍历的应用可以让我从数据库中获得我想要的内容。
优秀的答案!这真的为我清除了一切,谢谢。 –