[英]How can I conditionally add a vertex and multiple edges using Gremlin in Amazon Neptune?
我将 Amazon Neptune 用于个人项目,但在编写查询时遇到了问题。 我正在使用 Gremlin-Java 来查询和改变图形。
我能想到的表示不同输入所需输出的最好方法是用图表,所以下面是图表形式的问题陈述,分为 3 种情况。 最后,不需要完整的解决方案(尽管会被接受)——即使是朝着正确的方向轻推也将不胜感激!
这是我应该执行此突变的代码,但它必须有一个缺陷(或多个缺陷!),因为它在案例 1中根本没有改变图形,因此我无法测试案例 2 。 案例 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();
}
Function 致电:
createShard(
"john",
"newShard",
new HashSet<>(),
new HashSet<>()
)
Function 致电:
createShard(
"john",
"newShard",
new HashSet<>(Arrays.asList("firstShardToInherit", "secondShardToInherit")),
new HashSet<>(Arrays.asList("john", "userToInherit"))
)
Function 致电:
createShard(
"john",
"newShard",
new HashSet<>(Arrays.asList("userWhoDoesNotExist")),
new HashSet<>(),
)
所需的最终图 State:与初始图 state 相同。 如果突变查询会抛出像java.util.NoSuchElementException
这样的异常,或者给出一些其他指示图形没有被查询突变的指示,那将是理想的。
Function 致电:
createShard(
"john",
"newShard",
new HashSet<>(Arrays.asList()),
new HashSet<>(Arrays.asList("shardWhichDoesNotExist"))
)
所需的最终图 State:与初始图 state 相同。 如果突变查询会抛出像java.util.NoSuchElementException
这样的异常,或者给出一些其他指示图形没有被查询突变的指示,那将是理想的。
Function 致电:
createShard(
"john",
"existingShardName",
new HashSet<>(),
new HashSet<>()
)
所需的最终图 State:与初始图 state 相同。 如果突变查询会抛出异常或给出其他指示图没有被查询突变,那将是理想的,因为已经存在具有相同 label 和“shardName”属性的顶点。
这是一个复杂的问题,但我认为您的问题往往源于假设您的遍历将比实际执行的更多。 让我们以“案例 1”为例,它从仅存在一个“用户”顶点开始,“名称”为“约翰”。 您的遍历开始于:
g.V().hasLabel("shard).
has("shardName", P.within(inheritedShardNames)).as("inheritedShards")
由于图中现在有“分片”顶点,因此遍历立即不产生遍历器(即在 stream 中移动以携带数据的对象)并立即终止,因为没有任何东西可以触发下游步骤。 您似乎想要某种形式的 upsert 或“获取或创建”模式来解决您的问题。
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]
第一个gV().hasLabel('country').addV('person')
什么都不做,因为图中没有“国家”顶点,因此永远不会触发addV()
。 另一方面,在此之后的遍历确实添加了一个顶点,因为调用fold()
是一种归约操作,它将产生一个携带空List
object 的遍历器,这反过来又可以addV()
。
Gremlin 的 upsert 样式遍历的模式在很多地方都有描述。 请参见:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.