【问题标题】:How to inject map and filter based on map content in gremlin如何在gremlin中根据地图内容注入地图和过滤器
【发布时间】:2020-08-05 22:34:18
【问题描述】:

我正在运行 JanusGraph 服务器并从 gremlin 控制台连接到它。

可以看出,我有两个顶点,id属性设置为1和2

gremlin> g.addV('user').property('id', 1)
==>v[4224]
gremlin> g.addV('user').property('id', 2)
==>v[4192]
gremlin> g.V().valueMap()
==>{id=[2]}
==>{id=[1]}

接下来,我注入了一个具有不同属性的地图数组列表。我正在尝试遍历此地图并过滤顶点,但我无法弄清楚为什么查询不起作用。有人可以帮我找出正确的查询吗?

我尝试在 select("id") 之后使用终端步骤 next(),但也失败了。

gremlin> g.inject([["id": 1], ["id": 2, "something":"anything"]]).unfold().as("m").V().has("user", "id", select("m").select("id"))
Value [[SelectOneStep(last,m), SelectOneStep(last,id)]] is not an instance of the expected data type for property key [id] and cannot be converted. Expected: class java.lang.Integer, found: class org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.DefaultGraphTraversal
Type ':help' or ':h' for help.
Display stack trace? [yN]

我不能使用g.V().has(label, key, within(...)),因为我需要在多个地方使用同一张地图并为每一行重复步骤。

【问题讨论】:

  • has(..., Traversal) 被误解了。它旨在通过遍历 属性值 来过滤不产生结果的遍历器。这并不是说将select("m").select("id") 的结果注入has() 并使用该值来确定过滤器是否有效。使用Map 遍历的最终目标是什么?
  • @stephenmallette 最终目标是能够操纵几个顶点。假设输入是[["id": 1, "something":"anything1"], ["id": 2, "something":"anything2"]] 然后我希望能够一次性执行以下操作-> 找到 id 为“1”的用户顶点,然后去公司(大学)用户工作并在该顶点上添加任何属性1。 -> 找到 id 为“2”的用户顶点,然后去公司(大学)用户工作并在该顶点上添加属性anything2。 @stephenmallette

标签: gremlin janusgraph


【解决方案1】:

在这种情况下,我可能会采取不同的遍历方法并避免使用inject()。使用inject(),您将不得不展开您的Map 对象列表,然后对每个对象进行顶点查找,如果您的列表较长,这在所有图形系统上可能都很昂贵。我还想知道您是否可以编写遍历,使图形系统能够使用索引优化您的顶点查找。

鉴于所有这些以及您遍历更新找到顶点的属性的最终目标,我认为我会采用这种方法:

gremlin> g = TinkerGraph.open().traversal()
==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
gremlin> g.addV('user').property('id', 1)
==>v[0]
gremlin> g.addV('user').property('id', 2)
==>v[2]
gremlin> m = [["id": 1], ["id": 2, "something":"anything"]]
==>[id:1]
==>[id:2,something:anything]
gremlin> ids = m.collect{it.id}
==>1
==>2
gremlin> g.withSideEffect('m',m).
......1>   V().has('user','id',within(ids)).as('v').
......2>   sideEffect(select('m').unfold().
......3>              filter(select('id').as('ii').
......4>                     where('ii',eq('v')).
......5>                       by().
......6>                       by('id')).
......7>              unfold().as('kv').
......8>              select('v').
......9>              property(select('kv').by(keys),select('kv').by(values)))
==>v[0]
==>v[2]
gremlin> g.V().elementMap()
==>[id:0,label:user,id:1]
==>[id:2,label:user,id:2,something:anything]

在这里,我们通过单个查找找到所有带有within() 的顶点,然后通过当前顶点“id”属性查找filter() 的数据列表,然后更新属性。

【讨论】:

  • 感谢您的回答。我不希望地图的大小很大,可能是~10 行。这个解决方案解决了我原来的问题,但在我的情况下,可能有重复的条目。 [["id": 1], ["id": 2, "something":"anything"], ["id":1, "something1": "anything2]] 基本上,每张地图都包含一系列需要应用的指令,不仅在那个顶点上,而且在它的邻居上。这让我很难预处理和组合条目或在其中使用。尽管如此,你的解决方案解决了我原来的问题
  • 那么我想你会像以前一样使用inject(),这样每个Map都会有一个遍历器。
【解决方案2】:

尝试以下查询,它应该可以工作:

g.inject([["id": 1], ["id": 2, "something":"anything"]]).
  unfold().as("m").
  V().
  hasLabel("user").
  has("id", select("m").select("id")).
  dedup()

您的查询失败,因为has(label, propertyKey, traversal) 的语法无效。您可以使用has(label, propertyKey, propertyValue)has(label, propertyKey, predicate)

【讨论】:

  • 这个解决方案不起作用 :( gremlin> g.V().valueMap() ==>{id=[3]} ==>{id=[4]} ==>{id=[2]} ==>{id=[1]} 这给了我所有 4 个顶点,而不是只有两个 gremlin> g.inject([["id": 1], ["id": 2, "something":"anything"]]).unfold().as("m").V().hasLabel("user").has("id", select("m").select("id")).dedup().valueMap() ==>{id=[3]} ==>{id=[4]} ==>{id=[2]} ==>{id=[1]}
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-28
相关资源
最近更新 更多