如何用单条Gremlin语句实现顶点与边的不存在即创建?
问题:Gremlin单语句实现顶点与边的不存在则创建
我已经实现了通过Gremlin语句判断边不存在则创建的功能,以下代码运行正常:
g.V().hasLabel("V1") .has("userId", userId).as("a") .V().hasLabel("V1").has("userId", userId2) .coalesce( bothE("link").where(outV().as("a")), addE("link").from("a") )
但现在我需要在单条Gremlin语句中实现顶点与边均不存在时的创建操作。我尝试了以下代码,在新图环境中运行后仅成功创建了顶点,未建立顶点间的关联关系:
g.V().hasLabel("V1") .has("userId", userId).fold() .coalesce( unfold(), addV("V1").property("userId", userId1) ).as("a") .V().hasLabel("V1").has("userId", userId2).fold() .coalesce( unfold(), addV("V1").property("userId", userId2) ) .coalesce( bothE("link").where(outV().as("a")), addE("link").from("a") )
请问如何修改代码以实现需求?
解决方案
你遇到的问题其实是Gremlin遍历中as()标记的作用域问题——当你处理完第一个顶点并标记为"a"后,后续查询第二个顶点的步骤相当于开启了一个新的遍历分支,导致后面的边操作步骤找不到"a"的引用,自然没法创建关联。
要解决这个问题,我们需要确保两个顶点的引用在整个遍历流程中都能被访问到,同时把顶点的查询/创建和边的判断/创建整合在同一个上下文里。这里有两种可行的修改方式:
方式一:保留顶点标记并通过select()关联
g.V().hasLabel("V1").has("userId", userId1).fold() // 处理第一个顶点:存在则展开,不存在则创建 .coalesce(unfold(), addV("V1").property("userId", userId1)).as("a") // 处理第二个顶点,同样逻辑 .V().hasLabel("V1").has("userId", userId2).fold() .coalesce(unfold(), addV("V1").property("userId", userId2)).as("b") // 判断边是否存在,不存在则创建 .coalesce( // 检查a和b之间是否已有link边 __.select("a", "b").where(__.select("a").bothE("link").where(inV().as("b"))), // 不存在则从a到b创建link边 __.select("a").addE("link").to(__.select("b")) )
方式二:用match()步骤更清晰地定义顶点关系
match()步骤可以帮我们更直观地声明两个顶点的存在性逻辑,代码可读性更好:
g.match( // 确保顶点a存在(不存在则创建) __.as("a").coalesce(V().has("V1", "userId", userId1), addV("V1").property("userId", userId1)), // 确保顶点b存在(不存在则创建) __.as("b").coalesce(V().has("V1", "userId", userId2), addV("V1").property("userId", userId2)) ).coalesce( // 检查a和b之间的link边是否存在 __.select("a").bothE("link").where(inV().as("b")), // 不存在则创建边 __.select("a").addE("link").to(__.select("b")) )
关键注意点:
- 一定要保证两个顶点的标记(
"a"和"b")在边操作的步骤中是可访问的,不能让遍历分支打断引用链。 - 边的判断逻辑要明确检查两个顶点之间的关联,避免只检查单边方向导致的误判(比如用
bothE而不是outE,除非你明确需要固定方向)。
内容的提问来源于stack exchange,提问作者thangdc94
相关产品推荐
相关产品推荐

