唯一节点
这描述了如何在创建节点时确保属性的唯一性。
创建唯一节点
在许多用例中,实体之间需要一定程度的唯一性。例如,系统中可能只存在一个具有特定电子邮件地址的用户。如果多个并发线程天真地尝试创建用户,则会创建重复项。
以下是确保唯一性的主要策略,它们都适用于集群和单实例部署。
获取或创建
定义唯一性约束并使用 Cypher 的 MERGE
子句是获取或创建唯一节点的最有效方法。
示例的源代码可以在以下位置找到: GetOrCreateDocIT.java |
创建唯一性约束
try ( Transaction tx = graphdb.beginTx() )
{
tx.schema()
.constraintFor( Label.label( "User" ) )
.assertPropertyIsUnique( "name" )
.withName( "usernames" )
.create();
tx.commit();
}
使用 MERGE
创建唯一节点
Node result = null;
ResourceIterator<Node> resultIterator = null;
try ( Transaction tx = graphDb.beginTx() )
{
String queryString = "MERGE (n:User {name: $name}) RETURN n";
Map<String, Object> parameters = new HashMap<>();
parameters.put( "name", username );
resultIterator = tx.execute( queryString, parameters ).columnAs( "n" );
result = resultIterator.next();
tx.commit();
return result;
}
MERGE
子句要么对已存在的匹配节点进行读锁,要么进行写锁,并确保当前事务是唯一创建该节点的事务。
从技术上讲,可以使用锁定节点或锁定属性,但应尽可能避免。使用锁定节点模式很难正确执行,并且性能特征更差,因为它始终涉及写锁。
您可能还会倾向于使用 Java 同步进行悲观锁定,但这很危险。通过混合 Neo4j 和 Java 运行时中的锁,可能会产生 Neo4j 检测不到的死锁。只要所有锁定都由 Neo4j 完成,所有死锁都将被检测到并避免。
有关锁和死锁的更多信息,请参见 操作手册→锁和死锁。