嵌入式Neo4j中的逻辑节点删除

时间:2019-07-10 13:00:40

标签: neo4j neo4j-embedded

我在嵌入式Neo4j实例中有以下图形:

https://www.npmjs.com/package/javadoc

我想找到所有未被其他人欢迎的人。这很简单:MATCH (n) WHERE NOT ()-[:GREETS]->(n) RETURN n

但是,只要找到不打招呼的人,只要它匹配一个或多个节点,我都希望从数据库中删除那些节点并重复查询。换句话说,我要从图片中的图形开始:

  1. 运行查询,该查询返回“ Alice”
  2. 从数据库中删除“爱丽丝”
  3. 运行查询,返回“ Bob”
  4. 从数据库中删除“鲍勃”
  5. 运行查询,该查询不返回任何匹配项
  6. 返回名称“爱丽丝”和“鲍勃”

此外,我想执行此算法,而实际上没有从数据库中删除任何节点-即一种“逻辑删除”。

我发现的一种解决方案是在事务上调用success(),这样就不会将节点删除提交给数据库,如以下代码所示:

import org.neo4j.graphdb.*;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;

import java.io.File;
import java.util.*;

public class App 
{
    static String dbPath = "~/neo4j/data/databases/graph.db";

    private enum RelTypes implements RelationshipType { GREETS }

    public static void main(String[] args) {
        File graphDirectory = new File(dbPath);
        GraphDatabaseService graph = new GraphDatabaseFactory().newEmbeddedDatabase(graphDirectory);

        Set<String> notGreeted = new HashSet<>();

        try (Transaction tx = graph.beginTx()) {
            while (true) {
                Node notGreetedNode = getFirstNode(graph, "MATCH (n) WHERE NOT ()-[:GREETS]->(n) RETURN n");
                if (notGreetedNode == null) {
                    break;
                }
                notGreeted.add((String) notGreetedNode.getProperty("name"));
                detachDeleteNode(graph, notGreetedNode);
            }

            // Here I do NOT call tx.success()
        }

        System.out.println("Non greeted people: " + String.join(", ", notGreeted));

        graph.shutdown();
    }

    private static Node getFirstNode(GraphDatabaseService graph, String cypherQuery) {
        try (Result r = graph.execute(cypherQuery)) {
            if (!r.hasNext()) {
                return null;
            }

            Collection<Object> nodes = r.next().values();

            if (nodes.size() == 0) {
                return null;
            }

            return (Node) nodes.iterator().next();
        }
    }

    private static boolean detachDeleteNode(GraphDatabaseService graph, Node node) {
        final String query = String.format("MATCH (n) WHERE ID(n) = %s DETACH DELETE n", node.getId());

        try (Result r = graph.execute(query)) {
            return true;
        }
    }
}

此代码正常工作,并打印“未打招呼的人:鲍勃,爱丽丝”。

我的问题:这种方法(即在一个开放的事务中保持一系列数据库操作)是否有我应该意识到的任何缺点(例如潜在的内存问题)?我还有其他方法可以用来实现这一目标吗?

我还考虑过在节点上使用布尔属性将它们标记为已删除或未删除。我担心的是,我正在处理的实际应用程序包含数千个节点和各种类型的关系,并且实际查询是不平凡的,因此我宁愿不更改它们以容纳软删除布尔属性(但我我愿意这样做,如果事实证明这是最好的方法。

另外,请注意,我并不是在寻找不在周期内的节点。而是,基本思想如下。我有一些满足特定条件c的节点;我想(逻辑上)远程处理那些节点;这可能会使新节点满足相同条件c,依此类推,直到满足c的节点集为空为止。

0 个答案:

没有答案