【问题标题】:TinkerPop: Generic Query to combine and filter multiple traversalsTinkerPop:用于组合和过滤多个遍历的通用查询
【发布时间】:2018-09-12 04:21:13
【问题描述】:

样本数据:TinkerPop Modern Graph

条件:

  1. vadas2 hops 内连接到lop
  2. vadas3 hops 内连接到peter
  3. vadas 是否连接到 1 hops 中的 does-not-exists(不会给出任何结果的搜索)

具有预期结果的虚拟搜索

  1. 条件1 AND 2 => [vadas-marko-lop, vadas-marko-lop-peter]

  2. 条件13 => [vadas-marko-lop]


我能得到什么

  1. 条件12
gremlin> g.V().has("person", "name", "vadas").as("from")
.select("from").as("to1").repeat(both().as("to1")).times(2).emit().has("software", "name", "lop")
.select("from").as("to2").repeat(both().as("to2")).times(3).emit().has("person", "name", "peter")
.project("a", "b")
.by(select(all, "to1").unfold().values("name").fold())
.by(select(all, "to2").unfold().values("name").fold())
==>[a:[vadas,marko,lop],b:[vadas,marko,lop,peter]]
  1. 条件12
gremlin> g.V().has("person", "name", "vadas").as("nodes")
.union(repeat(both().as("nodes")).times(2).emit().has("software", "name", "lop"),
out().has("x", "y", "does-not-exist").as("nodes"))
.project("a")
.by(select(all, "nodes").unfold().values("name").fold())
==>[a:[vadas,marko,lop]]

那么如何实现这一点我有两种不同的查询格式,有没有办法编写一个可以同时做到的查询格式?


这没有用,这里有什么问题吗?不返回已经遍历的节点

g.V().has("person", "name", "vadas").as("nodes")
.or(
repeat(both().as("nodes")).times(2).emit().has("software", "name", "lop"), 
repeat(both().as("nodes")).times(3).emit().has("person", "name", "peter")
)
.project("a").by(select(all, "nodes").unfold().values("name").fold())
==>[a:[vadas]]
// Expect paths to be printed here vadas..lop, vadas...peter

【问题讨论】:

  • 我不能说我完全理解这个问题。 “通用”是什么意思?这似乎是您问题的重点,但不清楚这对我意味着什么。
  • andor 的逻辑我可以用两种不同的方法实现,有没有更好的方法来结合这两种方法?
  • 我还没关注。 Gremlin 有and()/or() 条件逻辑步骤,但我不知道您所说的“将这两者结合起来的更好方法”是什么意思?你是说你想要另一种方法来编写上面的遍历,不使用这两个步骤吗?
  • 我会更新帖子以尝试更好地解释
  • 我已经编辑了帖子,现在更好了吗?

标签: gremlin tinkerpop tinkerpop3 gremlin-server


【解决方案1】:

我不知道我是否理解您的需求,但如果您只需要查询模板之类的东西,那么也许这会有所帮助:

gremlin> conditions = [
......1>   [filter: {has("software", "name", "lop")},  distance: 2],
......2>   [filter: {has("person", "name", "peter")},  distance: 3],
......3>   [filter: {has("x", "y", "does-not-exist")}, distance: 1]]
==>[filter:groovysh_evaluate$_run_closure1@378bd86d,distance:2]
==>[filter:groovysh_evaluate$_run_closure2@2189e7a7,distance:3]
==>[filter:groovysh_evaluate$_run_closure3@69b2f8e5,distance:1]

gremlin> g = TinkerFactory.createModern().traversal()
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
gremlin> g.V().has("person", "name", "vadas").
......1>   union(repeat(both().simplePath()).
......2>           times(conditions[0].distance).
......3>           emit().
......4>         filter(conditions[0].filter()).store("x"),
......5>         repeat(both().simplePath()).
......6>           times(conditions[1].distance).
......7>           emit().
......8>         filter(conditions[1].filter()).store("x")).
......9>   barrier().
.....10>   filter(select("x").
.....11>          and(unfold().filter(conditions[0].filter()),
.....12>              unfold().filter(conditions[1].filter()))).
.....13>   path().
.....14>     by("name")
==>[vadas,marko,lop]
==>[vadas,marko,lop,peter]

gremlin> g.V().has("person", "name", "vadas").
......1>   union(repeat(both().simplePath()).
......2>           times(conditions[0].distance).
......3>           emit().
......4>         filter(conditions[0].filter()).store("x"),
......5>         repeat(both().simplePath()).
......6>           times(conditions[2].distance).
......7>           emit().
......8>         filter(conditions[2].filter()).store("x")).
......9>   barrier().
.....10>   filter(select("x").
.....11>          or(unfold().filter(conditions[0].filter()),
.....12>             unfold().filter(conditions[2].filter()))).
.....13>   path().
.....14>     by("name")
==>[vadas,marko,lop]

再抽象一点应该更清楚地表明这两个查询仅在 1 步上有所不同(andor):

apply = { condition ->
  repeat(both().simplePath()).
    times(condition.distance).
    emit().
  filter(condition.filter()).store("x")
}

verify = { condition ->
  unfold().filter(condition.filter())
}

// condition 1 AND 2   
g.V().has("person", "name", "vadas").
  union(apply(conditions[0]),
        apply(conditions[1])).
  barrier().
  filter(select("x").
         and(verify(conditions[0]),
             verify(conditions[1]))).
  path().
    by("name")

// condition 1 OR 3   
g.V().has("person", "name", "vadas").
  union(apply(conditions[0]),
        apply(conditions[2])).
  barrier().
  filter(select("x").
         or(verify(conditions[0]),
            verify(conditions[2]))).
  path().
    by("name")

【讨论】:

  • 非常感谢,所以filter 必须执行两次,看来or(...as("x"), ...as("y")) 不会将值存储到xy 中。我说的对吗?
  • 仅适用于当前路径,这对您的用例没有帮助,因为您的过滤条件取决于最终结果。
猜你喜欢
  • 2021-07-27
  • 1970-01-01
  • 1970-01-01
  • 2019-02-09
  • 1970-01-01
  • 2015-10-20
  • 1970-01-01
  • 2017-03-28
  • 1970-01-01
相关资源
最近更新 更多