TinkerPop无法检测同标签顶点,求实现存在检测及新增逻辑
正确实现TinkerGraph顶点存在性检测与新增的方案
先修正你代码里的基础问题
- 构造函数的graph覆盖问题:你在构造函数里传入了
graph参数,但随后又执行graph = TinkerGraph.open();,这会直接覆盖传入的实例,导致外部传入的Graph完全没用。如果是要使用外部传入的Graph,构造函数应该改成:
public TinkerTopGraph(Graph graph) { this.graph = graph; this.nodes = new HashMap<>(); this.g = traversal().withEmbedded(graph); }
如果是要新建独立的TinkerGraph,直接去掉构造参数即可。
核心逻辑的正确实现
根据你的需求,分两种场景给出代码:
场景1:根据顶点标签检测(即判断是否存在该标签的任意顶点,不存在则新增一个该标签的顶点)
这种场景下,使用Gremlin的fold().coalesce()原子操作(避免多次遍历的非原子性问题),必须调用终端步骤(比如next())触发遍历执行:
public void addEdge(Node sourceNode, Node destinationNode) { // 处理源顶点:查找标签匹配的顶点,无则新增 Vertex sourceVertex = g.V().hasLabel(sourceNode.toString()) .fold() .coalesce(unfold(), addV(sourceNode.toString())) .next(); // 处理目标顶点:逻辑同上 Vertex destVertex = g.V().hasLabel(destinationNode.toString()) .fold() .coalesce(unfold(), addV(destinationNode.toString())) .next(); // 添加边(可根据需求修改边的标签和属性) g.addE("linked") .from(sourceVertex) .to(destVertex) .next(); }
场景2:根据唯一属性检测(更常见:每个Node对应唯一顶点,比如根据Node的ID属性判断,而非标签)
如果你的需求是“Node对应的顶点是否存在(通过唯一标识),不存在则新增”,这才是多数业务场景的逻辑,此时要使用has(属性名, 属性值)来匹配:
public void addEdge(Node sourceNode, Node destinationNode) { // 假设Node类有getId()方法返回唯一标识,顶点标签统一为"Node" Vertex sourceVertex = g.V().has("id", sourceNode.getId()) .fold() .coalesce(unfold(), addV("Node").property("id", sourceNode.getId())) .next(); Vertex destVertex = g.V().has("id", destinationNode.getId()) .fold() .coalesce(unfold(), addV("Node").property("id", destinationNode.getId())) .next(); g.addE("connected") .from(sourceVertex) .to(destVertex) .next(); }
你之前写法的错误原因
- hasLabel/has的误用:
- 你用
has(sourceNode.toString())时,该方法是检查顶点是否存在名为该字符串的属性(不管值是什么),而非属性值匹配,完全不符合需求; - 如果你的
Node.toString()不是顶点标签,而是属性值,那hasLabel也用错了,应该用has(属性名, 属性值)。
- 你用
- fold().coalesce()未执行终端步骤:Gremlin遍历是惰性的,只写
fold().coalesce(...)不会实际触发数据库操作,必须加next()或iterate()才会执行。 - orElseGet的语法错误:Java中
orElseGet需要传入Supplier类型的参数,正确写法是用Lambda表达式:
你之前用的是Groovy闭包语法,在Java环境下会报错。Vertex sourceVertex = g.V().hasLabel(sourceNode.toString()) .tryNext() .orElseGet(() -> g.addV(sourceNode.toString()).next());
内容的提问来源于stack exchange,提问作者Γιάννης Κεσσόπουλος
相关产品推荐
相关产品推荐

