唯一节点
本文描述了在创建节点时如何确保属性的唯一性。
创建唯一节点
在许多使用场景中,实体之间需要一定程度的唯一性。例如,系统中只能存在一个具有特定电子邮件地址的用户。如果多个并发线程天真地尝试创建该用户,就会产生重复记录。
以下是确保唯一性的主要策略,它们在集群和单实例部署中均可工作。
获取或创建
定义唯一约束并使用 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 管理,所有死锁都会被检测并避免。
有关锁和死锁的更多信息,请参阅 操作手册 → 锁与死锁。