如何通过Cypher清理图形中的所有节点和关系的最佳方法是什么?
截至2022年7月,以下列出了四个选项:
- 选项1:MATCH(x)DETACH DELETE x
- 选项2:在事务中调用 {}
- 选项3:删除数据目录
- 选项4:在代码中删除
选项1:MATCH(x)DETACH DELETE x - 仅适用于小型数据集
正如您在问题中发布的那样,以下内容很好,但仅适用于节点和关系不太多的情况:
MATCH (x) DETACH DELETE x
如果节点和/或关系的数量足够大,这种方法将无法运行。以下是针对
http://localhost:7474/browser/
的“无法运行”示例:
没有足够的内存执行当前任务。请尝试在 neo4j 配置中增加 'dbms.memory.heap.max_size'(通常在 'conf/neo4j.conf' 中,如果您使用 Neo4j Desktop,则可以通过用户界面找到),或者如果您正在运行嵌入式安装,则使用 '-Xmx' 命令行标志增加堆大小,然后重新启动数据库。
以下是在
neo4j
控制台输出(或日志中,如果您已启用该功能)中显示的内容:
Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "neo4j.Scheduler-1"
选项2:在事务中调用{} - 2022年7月之前不起作用
根据neo4j文档,从版本4.4开始,另一种选择是使用新的CALL {} IN TRANSACTIONS
功能:
在4.4及更高版本中,您可以利用CALL {} IN TRANSACTIONS
语法[...]以批处理方式删除匹配记录的子集,直到完全删除为止
不幸的是,在我的测试中,这并不起作用。以下是一个仅尝试删除关系的示例:
MATCH ()-[r]-()
CALL { WITH r DELETE r }
IN TRANSACTIONS OF 1000 ROWS
在浏览器中运行会导致以下错误:
使用“CALL { ... } IN TRANSACTIONS”的查询只能在隐式事务中执行,但尝试在显式事务中执行。
在代码中,它产生相同的结果。这里是一个通过Java使用Bolt连接的尝试:
session.executeWrite(tx -> tx.run("MATCH (x) " +
"CALL { WITH x DETACH DELETE x } " +
"IN TRANSACTIONS OF 10000 ROWS"));
由此产生了与浏览器显示完全相同的错误:
org.neo4j.driver.exceptions.DatabaseException: A query with 'CALL { ... } IN TRANSACTIONS' can only be executed in an implicit transaction, but tried to execute in an explicit transaction.
at org.neo4j.driver.internal.util.Futures.blockingGet(Futures.java:111)
at org.neo4j.driver.internal.InternalTransaction.run(InternalTransaction.java:58)
at org.neo4j.driver.internal.AbstractQueryRunner.run(AbstractQueryRunner.java:34)
看一下
事务文档,它说:“事务可以是显式的或隐式的。”有什么区别?从同一文档中获得以下信息:
显式事务:
- 由用户打开。
- 可以按顺序执行多个Cypher查询。
- 由用户提交或回滚。
隐式事务,有时称为自动提交事务或:auto
事务:
- 会自动打开。
- 只能执行单个Cypher查询。
- 当查询成功完成时,将自动提交。
我无法确定如何打开隐式事务(因此,无法使用
'CALL { ... } IN TRANSACTIONS'
结构),因此这显然是一个死胡同。
在2022年5月31日发布的
Neo4j AuraDB Office Hours中,他们尝试在AuraDB中使用相同的功能。 它对他们也不起作用,尽管行为与我在Neo4j Community中观察到的不同。 我猜他们会在某个时候解决这个问题,感觉像是一个错误,但至少现在它又证实了
'CALL { ... } IN TRANSACTIONS'
不是前进的方法。
选项3:删除数据目录-适用于任何大小的数据集
这是最简单、最直接的机制,实际上也有效:
以下是它的样子:
% ./bin/neo4j stop
% rm -rf data/databases data/transactions
% ./bin/neo4j start
这很简单。你可以编写一个脚本来捕获这个作为一个单一的命令。
选项4:在代码中删除 - 可以处理任何大小的数据集
下面是一个最小的Java程序,处理所有节点和关系的删除,无论有多少个。手动删除选项可以正常工作,但我需要一种在代码中删除所有节点和关系的方法。这适用于Neo4j Community 4.4.3,由于我仅使用基本功能(没有扩展),我认为这也适用于其他范围的Neo4j版本,以及可能是AuraDB。
import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.GraphDatabase;
import org.neo4j.driver.Session;
public static void main(String[] args) throws InterruptedException {
String boltUri = "...";
String user = "...";
String password = "...";
Session session = GraphDatabase.driver(boltUri, AuthTokens.basic(user, password)).session();
int count = 1;
while (count > 0) {
session.executeWrite(tx -> tx.run("MATCH (x) WITH x LIMIT 1000 DETACH DELETE x"));
count = session.executeWrite(tx -> tx.run("MATCH (x) RETURN COUNT(x)").single().values().get(0).asInt());
}
}