在投影中重用 Where Step 的结果
Reuse the result of Where Step in projection
我得到了一个示例图,可以使用以下 DSL 构建:
g.addV('A').property(id, 'A1')
g.addV('B').property(id, 'B1').addE('B').from(V('A1'))
g.addV('B').property(id, 'B2').addE('B').from(V('A1'))
g.addV('C').property(id, 'C1').addE('C').from(V('B1'))
g.addV('C').property(id, 'C2').addE('C').from(V('B2'))
g.addV('BB').property(id, 'BB1').property('age', 2).addE('BB').from(V('B2'))
g.addV('BB').property(id, 'BB2').addE('BB').from(V('B2'))
g.addV('BB').property(id, 'BB3').addE('BB').from(V('B1'))
我想从带有标签 A 的顶点开始遍历,通过带有标签 'B'、'C' 的边,并输出每个 'B' 附加 'BB' 的所有路径顶点,我可以设法得到结果使用:
g.V().hasLabel('A').as('a').
out('B').as('b').
out('C').as('c').
project('shop', 'product', 'spec', 'device').
by(select('a').valueMap(true)).
by(select('b').valueMap(true)).
by(select('b').out('BB').valueMap(true).fold()).
by(select('c').valueMap(true))
然后我运行进入另一个场景,我必须过滤条件为'BB'的'B'个顶点,可以通过以下方式实现:
g.V().hasLabel('A').as('a').
out('B').where(out('BB').has('age', 2)).as('b').
out('C').as('c').
project('shop', 'product', 'spec', 'device').
by(select('a').valueMap(true)).
by(select('b').valueMap(true)).
by(select('b').out('BB').has('age', 2).valueMap(true).fold()).
by(select('c').valueMap(true))
我的问题是:我可以在 Projection 中再次使用 Where Step 的结果而不是过滤 'BB' 吗?
感谢任何帮助。
在您的方法的上下文中,不,您不能简单地在 where()
中重复使用遍历的结果。原因很简单,因为 where()
没有完全迭代结果 - 它寻求相当于 hasNext()
的内容来检测 Iterator
.[=25= 中的第一项]
因此,根据 has('age',2)
的选择性以及 where()
实际上只是在寻找一个结果这一事实,该遍历的成本可能不会非常昂贵,您可能会接受它遍历两次。如果它是 "expensive" 并且您的图形支持某种以顶点为中心的索引,您可以将 "age" 非规范化为 "BB" 边,然后只执行 where(outE('BB').has('age',2))
.
可能查看它的另一种方法是稍微简化您的遍历。既然用了步长标签,为什么不去掉project()
,直接遍历"BB":
gremlin> g.V().hasLabel('A').as('shop').
......1> out('B').as('product').
......2> out('BB').has('age', 2).as('spec').
......3> select('product').
......4> out('C').as('device').
......5> select('shop', 'product', 'spec', 'device').
......6> by(valueMap(true))
==>[shop:[id:A1,label:A],product:[id:B2,label:B],spec:[id:BB1,label:BB,age:[2]],device:[id:C2,label:C]]
这是一个更具可读性的遍历,但对您的数据和结果的形状做出了一些假设,这些假设可能与您对 project()
所做的不完全匹配。我想通过一些 Gremlin 集合操作,您可以恢复 "spec" 周围的分组,但随后可读性开始崩溃。
以下方法似乎牺牲了一些可读性来执行 out('BB').has('age',2)
一次:
gremlin> g.V().hasLabel('A').as('shop').
......1> out('B').as('product').
......2> project('s').
......3> by(out('BB').has('age', 2).valueMap(true).fold()).as('spec').
......4> where(select('s').unfold()).
......5> select('product').
......6> out('C').as('device').
......7> select('shop', 'product', 'spec', 'device').
......8> by(valueMap(true)).
......9> by(valueMap(true)).
.....10> by(select('s')).
.....11> by(valueMap(true))
==>[shop:[id:A1,label:A],product:[id:B2,label:B],spec:[[id:BB1,label:BB,age:[2]]],device:[id:C2,label:C]]
如果我是第一次看到这个,我会立即想知道第 2-4 行的意义在哪里。目前尚不清楚 project('s')
生成的 Map
的全部意义在于完全实现 out('BB').has('age', 2)
的结果,以便可以在第 4 行使用它们来过滤掉那些遍历器。我认为我们不会经常推荐这种方法,除非在这种情况下无论如何您都需要实现整个结果。如果只有一个结果,那么你需要所有的结果,所以最好先把它们都拿下来。
我得到了一个示例图,可以使用以下 DSL 构建:
g.addV('A').property(id, 'A1')
g.addV('B').property(id, 'B1').addE('B').from(V('A1'))
g.addV('B').property(id, 'B2').addE('B').from(V('A1'))
g.addV('C').property(id, 'C1').addE('C').from(V('B1'))
g.addV('C').property(id, 'C2').addE('C').from(V('B2'))
g.addV('BB').property(id, 'BB1').property('age', 2).addE('BB').from(V('B2'))
g.addV('BB').property(id, 'BB2').addE('BB').from(V('B2'))
g.addV('BB').property(id, 'BB3').addE('BB').from(V('B1'))
我想从带有标签 A 的顶点开始遍历,通过带有标签 'B'、'C' 的边,并输出每个 'B' 附加 'BB' 的所有路径顶点,我可以设法得到结果使用:
g.V().hasLabel('A').as('a').
out('B').as('b').
out('C').as('c').
project('shop', 'product', 'spec', 'device').
by(select('a').valueMap(true)).
by(select('b').valueMap(true)).
by(select('b').out('BB').valueMap(true).fold()).
by(select('c').valueMap(true))
然后我运行进入另一个场景,我必须过滤条件为'BB'的'B'个顶点,可以通过以下方式实现:
g.V().hasLabel('A').as('a').
out('B').where(out('BB').has('age', 2)).as('b').
out('C').as('c').
project('shop', 'product', 'spec', 'device').
by(select('a').valueMap(true)).
by(select('b').valueMap(true)).
by(select('b').out('BB').has('age', 2).valueMap(true).fold()).
by(select('c').valueMap(true))
我的问题是:我可以在 Projection 中再次使用 Where Step 的结果而不是过滤 'BB' 吗?
感谢任何帮助。
在您的方法的上下文中,不,您不能简单地在 where()
中重复使用遍历的结果。原因很简单,因为 where()
没有完全迭代结果 - 它寻求相当于 hasNext()
的内容来检测 Iterator
.[=25= 中的第一项]
因此,根据 has('age',2)
的选择性以及 where()
实际上只是在寻找一个结果这一事实,该遍历的成本可能不会非常昂贵,您可能会接受它遍历两次。如果它是 "expensive" 并且您的图形支持某种以顶点为中心的索引,您可以将 "age" 非规范化为 "BB" 边,然后只执行 where(outE('BB').has('age',2))
.
可能查看它的另一种方法是稍微简化您的遍历。既然用了步长标签,为什么不去掉project()
,直接遍历"BB":
gremlin> g.V().hasLabel('A').as('shop').
......1> out('B').as('product').
......2> out('BB').has('age', 2).as('spec').
......3> select('product').
......4> out('C').as('device').
......5> select('shop', 'product', 'spec', 'device').
......6> by(valueMap(true))
==>[shop:[id:A1,label:A],product:[id:B2,label:B],spec:[id:BB1,label:BB,age:[2]],device:[id:C2,label:C]]
这是一个更具可读性的遍历,但对您的数据和结果的形状做出了一些假设,这些假设可能与您对 project()
所做的不完全匹配。我想通过一些 Gremlin 集合操作,您可以恢复 "spec" 周围的分组,但随后可读性开始崩溃。
以下方法似乎牺牲了一些可读性来执行 out('BB').has('age',2)
一次:
gremlin> g.V().hasLabel('A').as('shop').
......1> out('B').as('product').
......2> project('s').
......3> by(out('BB').has('age', 2).valueMap(true).fold()).as('spec').
......4> where(select('s').unfold()).
......5> select('product').
......6> out('C').as('device').
......7> select('shop', 'product', 'spec', 'device').
......8> by(valueMap(true)).
......9> by(valueMap(true)).
.....10> by(select('s')).
.....11> by(valueMap(true))
==>[shop:[id:A1,label:A],product:[id:B2,label:B],spec:[[id:BB1,label:BB,age:[2]]],device:[id:C2,label:C]]
如果我是第一次看到这个,我会立即想知道第 2-4 行的意义在哪里。目前尚不清楚 project('s')
生成的 Map
的全部意义在于完全实现 out('BB').has('age', 2)
的结果,以便可以在第 4 行使用它们来过滤掉那些遍历器。我认为我们不会经常推荐这种方法,除非在这种情况下无论如何您都需要实现整个结果。如果只有一个结果,那么你需要所有的结果,所以最好先把它们都拿下来。