3

我一直在尝试为我一直在开发的个人 web 应用程序找出数据库后端。由于我在数据中需要的灵活性,关系数据库是不可行的,并且可能需要某种形式的文档存储。当我了解图形数据库时,我觉得这将是完美的。

但是,我遇到了一个问题:我需要能够以某种方式定义三向关系。我还没有决定数据库,但我一直在修补 Neo4j,所以我将使用 Cypher 来描述这个问题。

本质上,我从这个开始:

(a:N)-[r:E]->(b:N)

我需要的是一种将多个节点不仅与 a 和 b,而且与 r 相关联的方法。这些其他节点将存储关于所有 3 的不同信息。我决定可能只有两种方法来处理这个问题:将关系存储在自己的节点中或存储对包含信息的节点的引用并创建伪边. 我认为前者可能是一个更好的主意,可以为我们提供更像这样的东西:

(a:N)<-[:E]-(r:R)->[:E](b:N)
(s:S)->(a)
(s)->(r)
(s)->(b)

所以,现在,这导致了查询数据的问题。使用图形数据库的重点在于能够遍历图形。如果我做这样的事情,有没有办法在 N 类型的节点之间递归遍历?处理这个的正确方法是什么?我已经想到了几种不同的方法来处理这个问题,但它们都有自己的缺点。是否有特定的图形数据库本机支持这种类型的功能?

更新

使用原始代码,我能够使用以下代码递归遍历节点:

MATCH (a:N)-[:E*]->(b:N)
RETURN a,b

但是,一旦我将边缘拉出超边缘,我就无法弄清楚是否有一种方法可以递归地遍历图形到未确定的深度,因为我将交替使用节点类型。我正在寻找类似的东西

MATCH chain=((a:N)-[]->(r:R)-[]->(b:N))*
RETURN [nodes of type N along the chain]

如果答案只是在创建超边的同时在 a 和 b 之间创建一条边,那么我的问题就变成了:有没有一种好的方法可以确保边和超边一起被移除?基本上,两者都感觉像是一种变通方法,而不是实际的解决方案。

4

3 回答 3

6

您描述的场景由提到的超边模式@Pangea 在属性图模型中处理。您基本上将边缘(需要边缘进出它)转换为顶点。对于图表,我认为它不是一种非规范化,而是一种不同的建模抽象。

就边对边的原生支持而言,您标记问题的图表都没有直接支持这样的功能。由于您确实包含了 Titan 和 OrientDB,我假设您也在评估 TinkerPop 作为您的解决方案的可能部分,我可以进一步说,由于蓝图不支持边上的边,所以蓝图图也不支持。

就遍历而言,我不能说我完全遵循“递归遍历”的意思。如果您能详细说明一下,我可以尝试修改我的答案。我将添加这个简单的示例,说明如何从“a”顶点遍历以查找 Gremlin 中的所有其他相关顶点(对不起,我不知道 Cypher):

gremlin> g = new TinkerGraph()
==>tinkergraph[vertices:0 edges:0]
gremlin> va = g.addVertex([type:'N',name:'a'])
==>v[0]
gremlin> er = g.addVertex([type:'R',name:'r'])
==>v[1]
gremlin> vb = g.addVertex([type:'N',name:'b'])
==>v[2]
gremlin> vc = g.addVertex([type:'N',name:'c'])
==>v[5]
gremlin> va.addEdge('e',er)
==>e[3][0-e->1]
gremlin> vb.addEdge('e',er)
==>e[4][2-e->1]
gremlin> vc.addEdge('e',er)                   
==>e[6][5-e->1]
gremlin> va.out.in.except([va]).name
==>c
==>b
gremlin> vd = g.addVertex([type:'N',name:'d'])
==>v[7]
gremlin> es = g.addVertex([type:'R',name:'s'])
==>v[8]
gremlin> vb.addEdge('e',es)
==>e[9][2-e->8]
gremlin> vd.addEdge('e',es)
==>e[10][7-e->8]
gremlin> x=[];va.aggregate(x).out.in.except(x).loop(4){it.loops<2}.name
==>c
==>b
gremlin> x=[];va.aggregate(x).out.in.except(x).loop(4){it.loops<3}.name
==>d

关于:

如果答案只是在创建超边的同时在 a 和 b 之间创建一条边,那么我的问题就变成了:有没有一种好的方法可以确保边和超边一起被移除?

当您删除“超边”顶点时,您将自动删除与其相连的边,因此您可以有效地将它们一起删除。

于 2013-12-28T13:17:22.477 回答
1

是否有特定的图形数据库本机支持这种类型的功能?

确实有!Grakn 支持原生超边,relation在其语法中称为 a。匹配关系及其相关元素的最简洁方式如下所示:

match ($a, $b, $r) isa E; get;

全面披露:我在 Grakn 工作;)

于 2020-07-16T17:07:28.133 回答
0

查看Neo4j 文档中的Hyperedges模式。

于 2013-12-28T02:43:36.837 回答