简体   繁体   English

如何在 Amazon Neptune 中使用 Gremlin 有条件地添加顶点和多条边?

[英]How can I conditionally add a vertex and multiple edges using Gremlin in Amazon Neptune?

I'm using Amazon Neptune for a personal project and I'm having trouble writing a query.我将 Amazon Neptune 用于个人项目,但在编写查询时遇到了问题。 I'm using Gremlin-Java to query and mutate the graph.我正在使用 Gremlin-Java 来查询和改变图形。

The best way I can think of to represent the desired outputs for different inputs is with diagrams, so below is the problem statement in diagram form, broken into 3 cases.我能想到的表示不同输入所需输出的最好方法是用图表,所以下面是图表形式的问题陈述,分为 3 种情况。 Lastly, a full solution isn't necessary (though would be accepted) - even a nudge in the right direction would be much appreciated!最后,不需要完整的解决方案(尽管会被接受)——即使是朝着正确的方向轻推也将不胜感激!

Here's the code I have that should perform this mutation, but it must have a flaw (or multiple flaws!) because it doesn't mutate the graph at all in Case 1 and I've thus been unable to test Case 2 .这是我应该执行此突变的代码,但它必须有一个缺陷(或多个缺陷!),因为它在案例 1中根本没有改变图形,因此我无法测试案例 2 Case 3 , Case 4 , and Case 5 would also not exhibit the desired behavior with this code.案例 3案例 4案例 5也不会使用此代码表现出所需的行为。

void createShard(String username, String shardName, Set<String> inheritedShardNames, Set<String> inheritedUsers) {}
    g.V()
        .hasLabel("shard)
        .has("shardName", P.within(inheritedShardNames))
        .as("inheritedShards")
    .V()
        .hasLabel("user")
        .has("username", P.within(inheritedUsers))
        .as("inheritedUsers")
    .V()
        .has("user", "username", username)
        .as("user")
    .addV("shard)
        .property(single, "shardName", shardName)
        .property(single, "createdAt", new Date())
        .as("newShard")
    .addE("shardInheritsShard").from("newShard").to("inheritedShards")
    .addE("shardInheritsUser").from("newShard").to("inheritedUsers")
    .addE("userOwnsShard").from("user").to("newShard")
    .addE("userFollowsShard").from("user").to("newShard")
    .iterate();
}

Case 1情况1

Function call: Function 致电:

createShard(
    "john",
    "newShard",
    new HashSet<>(),
    new HashSet<>()
)

Initial Graph State UML 初始图 State UML

Desired Final Graph State UML 所需的最终图表 State UML

Case 2案例二

Function call: Function 致电:

createShard(
    "john",
    "newShard",
    new HashSet<>(Arrays.asList("firstShardToInherit", "secondShardToInherit")),
    new HashSet<>(Arrays.asList("john", "userToInherit"))
)

Initial Graph State UML 初始图 State UML

Desired Final Graph State UML 所需的最终图表 State UML

Case 3案例3

Function call: Function 致电:

createShard(
    "john",
    "newShard",
    new HashSet<>(Arrays.asList("userWhoDoesNotExist")),
    new HashSet<>(),
)

Initial Graph State UML 初始图 State UML

Desired Final Graph State: Same as initial graph state.所需的最终图 State:与初始图 state 相同。 Would be ideal if the mutation query would throw an exception like java.util.NoSuchElementException or give some other indication that the graph wasn't mutated by the query.如果突变查询会抛出像java.util.NoSuchElementException这样的异常,或者给出一些其他指示图形没有被查询突变的指示,那将是理想的。

Case 4案例4

Function call: Function 致电:

createShard(
    "john",
    "newShard",
    new HashSet<>(Arrays.asList()),
    new HashSet<>(Arrays.asList("shardWhichDoesNotExist"))
)

Initial Graph State UML 初始图 State UML

Desired Final Graph State: Same as initial graph state.所需的最终图 State:与初始图 state 相同。 Would be ideal if the mutation query would throw an exception like java.util.NoSuchElementException or give some other indication that the graph wasn't mutated by the query.如果突变查询会抛出像java.util.NoSuchElementException这样的异常,或者给出一些其他指示图形没有被查询突变的指示,那将是理想的。

Case 5案例5

Function call: Function 致电:

createShard(
    "john",
    "existingShardName",
    new HashSet<>(),
    new HashSet<>()
)

Initial Graph State UML 初始图 State UML

Desired Final Graph State: Same as initial graph state.所需的最终图 State:与初始图 state 相同。 Would be ideal if the mutation query would throw an exception or give some other indication that the graph wasn't mutated by the query because a vertex with the same label and "shardName" property already exists.如果突变查询会抛出异常或给出其他指示图没有被查询突变,那将是理想的,因为已经存在具有相同 label 和“shardName”属性的顶点。

This is a complex question but I think your problems tend to stem from assuming that more your traversal will execute than what actually is.这是一个复杂的问题,但我认为您的问题往往源于假设您的遍历将比实际执行的更多。 Let's take "Case 1" as an example where it starts with just one "user" vertex in existence with the "name" of "john".让我们以“案例 1”为例,它从仅存在一个“用户”顶点开始,“名称”为“约翰”。 Your traversal begins as:您的遍历开始于:

g.V().hasLabel("shard).
  has("shardName", P.within(inheritedShardNames)).as("inheritedShards")

As there are now "shard" vertices in the graph, the traversal immediately produces no traversers (ie objects that travel in the stream to carry the data) and immediately terminates as there is nothing to trigger downstream steps.由于图中现在有“分片”顶点,因此遍历立即不产生遍历器(即在 stream 中移动以携带数据的对象)并立即终止,因为没有任何东西可以触发下游步骤。 It seems that you want some form of upsert or "get or create" sort of pattern to solve your problem.您似乎想要某种形式的 upsert 或“获取或创建”模式来解决您的问题。

A quick example in Gremlin Console demonstrates the issue: Gremlin Console 中的一个简单示例演示了该问题:

gremlin> g = TinkerFactory.createModern().traversal()
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
gremlin> g.V().hasLabel('country').addV('person')
gremlin> g.V().hasLabel('country').fold().addV('person')
==>v[13]

The first gV().hasLabel('country').addV('person') does nothing because there are no "country" vertices in the graph and therefore addV() is never triggered.第一个gV().hasLabel('country').addV('person')什么都不做,因为图中没有“国家”顶点,因此永远不会触发addV() On the other hand, the traversal following that one does add a vertex because calling fold() is a reducing operation that will produce a traverser carrying a List object that is empty, which in turn enables addV() to be called.另一方面,在此之后的遍历确实添加了一个顶点,因为调用fold()是一种归约操作,它将产生一个携带空List object 的遍历器,这反过来又可以addV()

The patterns for upsert-style traversals with Gremlin are described in a variety of places. Gremlin 的 upsert 样式遍历的模式在很多地方都有描述。 Please see:请参见:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM