遍历有限制的图
traversing a graph with restrictions
我正在探索 TinkerPop 和 Gremlin,想了解 language/syntax 是否支持以下图形问题和遍历
(我想如果是这样的话,TinkerPop "enabled" 图 [AWS Neptun/OrientDB/Girafe/..] 也会支持它吗?)
(如果您知道任何可以满足我要求的图形数据库,请告诉我)
假设我们有:
- 3 种类型的顶点:A、B、C
- 3 种边缘类型:硬、中、软
任何两个顶点都可以通过任何类型的边连接
例如
我们的输入:
- 起始顶点
- 要查找的值
我们的output/answer:
从 'input vertex' 开始,找到 type/label 'A' 的任何顶点,其值等于 'input value'
我们的限制:
图的遍历必须遵循以下规则:
- 从顶点 'A' 我们只能通过边 type/label 移动到顶点 'B'
'Hard'
- 如果edge.label == 'Medium' || 我们可以从 B 或 C 移动到 B 或 C edge.label == 'Hard'
- 只有当edge.label == 'Hard'
我们才能从C移动到A
p.s。答案可以是路径或子树或节点的 id 或 yes/no
我不管,只要能答出图的问题
例如(来自上图示例)
输入: 顶点 ID = 3 & 值 = 56
输出: 顶点 ID = 5
让我们从你的示例图开始(在以后的问题中,如果你能提供这个脚本就好了):
g = TinkerGraph.open().traversal()
g.addV('A').
property(id, 3). /* should probably be 56 */
property('Value', 6).as('A3').
addV('A').
property(id, 4).
property('Value', 56).as('A4').
addE('soft').from('A4').
addV('A').
property(id, 5).
property('Value', 56).as('A5').
addV('B').
property(id, 1).
property('Value', '0x11').as('B1').
addE('hard').from('A3').
addV('B').
property(id, 2).
property('Value', '0x01').as('B2').
addE('med').from('B1').
addV('C').
property(id, 7).
property('Value', 'S').as('C7').
sideEffect(addE('soft').from('B1')).
addE('hard').to('A5').
addV('C').
property(id, 8).
property('Value', 'J').
sideEffect(addE('hard').from('B2')).
sideEffect(addE('med').to('C7')).
addE('med').from('A3').
iterate()
按照您的遍历规则进行的遍历为:
g.V(3).as('input'). /* don't filter by 'Value', filtering by id is enough */
repeat(choose(label).
option('A', out('hard').hasLabel('B')).
option('B', out('med','hard').hasLabel('B', 'C')).
option('C', union(out('med','hard').hasLabel('B', 'C'),
out('hard').hasLabel('A'))).
dedup()).
emit(where(eq('input')).by('Value'))
...但正如我在评论中提到的,您的示例图表存在问题。
但是,如果我将顶点 3 的 Value
更改为 56
,我们得到:
gremlin> g.V(3).as('input').
......1> repeat(choose(label).
......2> option('A', out('hard').hasLabel('B')).
......3> option('B', out('med','hard').hasLabel('B', 'C')).
......4> option('C', union(out('med','hard').hasLabel('B', 'C'),
......5> out('hard').hasLabel('A'))).
......6> dedup()).
......7> emit(where(eq('input')).by('Value'))
==>v[5]
我正在探索 TinkerPop 和 Gremlin,想了解 language/syntax 是否支持以下图形问题和遍历
(我想如果是这样的话,TinkerPop "enabled" 图 [AWS Neptun/OrientDB/Girafe/..] 也会支持它吗?)
(如果您知道任何可以满足我要求的图形数据库,请告诉我)
假设我们有:
- 3 种类型的顶点:A、B、C
- 3 种边缘类型:硬、中、软
任何两个顶点都可以通过任何类型的边连接
例如
我们的输入:
- 起始顶点
- 要查找的值
我们的output/answer:
从 'input vertex' 开始,找到 type/label 'A' 的任何顶点,其值等于 'input value'
我们的限制:
图的遍历必须遵循以下规则:
- 从顶点 'A' 我们只能通过边 type/label 移动到顶点 'B' 'Hard'
- 如果edge.label == 'Medium' || 我们可以从 B 或 C 移动到 B 或 C edge.label == 'Hard'
- 只有当edge.label == 'Hard' 我们才能从C移动到A
p.s。答案可以是路径或子树或节点的 id 或 yes/no 我不管,只要能答出图的问题
例如(来自上图示例)
输入: 顶点 ID = 3 & 值 = 56
输出: 顶点 ID = 5
让我们从你的示例图开始(在以后的问题中,如果你能提供这个脚本就好了):
g = TinkerGraph.open().traversal()
g.addV('A').
property(id, 3). /* should probably be 56 */
property('Value', 6).as('A3').
addV('A').
property(id, 4).
property('Value', 56).as('A4').
addE('soft').from('A4').
addV('A').
property(id, 5).
property('Value', 56).as('A5').
addV('B').
property(id, 1).
property('Value', '0x11').as('B1').
addE('hard').from('A3').
addV('B').
property(id, 2).
property('Value', '0x01').as('B2').
addE('med').from('B1').
addV('C').
property(id, 7).
property('Value', 'S').as('C7').
sideEffect(addE('soft').from('B1')).
addE('hard').to('A5').
addV('C').
property(id, 8).
property('Value', 'J').
sideEffect(addE('hard').from('B2')).
sideEffect(addE('med').to('C7')).
addE('med').from('A3').
iterate()
按照您的遍历规则进行的遍历为:
g.V(3).as('input'). /* don't filter by 'Value', filtering by id is enough */
repeat(choose(label).
option('A', out('hard').hasLabel('B')).
option('B', out('med','hard').hasLabel('B', 'C')).
option('C', union(out('med','hard').hasLabel('B', 'C'),
out('hard').hasLabel('A'))).
dedup()).
emit(where(eq('input')).by('Value'))
...但正如我在评论中提到的,您的示例图表存在问题。
但是,如果我将顶点 3 的 Value
更改为 56
,我们得到:
gremlin> g.V(3).as('input').
......1> repeat(choose(label).
......2> option('A', out('hard').hasLabel('B')).
......3> option('B', out('med','hard').hasLabel('B', 'C')).
......4> option('C', union(out('med','hard').hasLabel('B', 'C'),
......5> out('hard').hasLabel('A'))).
......6> dedup()).
......7> emit(where(eq('input')).by('Value'))
==>v[5]