Java 如何仅在neo4j中不存在节点时创建新节点
我正在使用neo4j和vertx 我使用的是Neo4jJDBC 我设法创建了用户,但我如何“升级”此查询以创建新用户(具有唯一索引),前提是该用户不存在。 用户ID应该是主键Java 如何仅在neo4j中不存在节点时创建新节点,java,neo4j,spring-data-neo4j,Java,Neo4j,Spring Data Neo4j,我正在使用neo4j和vertx 我使用的是Neo4jJDBC 我设法创建了用户,但我如何“升级”此查询以创建新用户(具有唯一索引),前提是该用户不存在。 用户ID应该是主键 private final Logger logger = Logger.getLogger(Neo4jRepo.class); private Connection conn = null; public Neo4jRepo() { logger.debug("Neo4jRepo, I
private final Logger logger = Logger.getLogger(Neo4jRepo.class);
private Connection conn = null;
public Neo4jRepo() {
logger.debug("Neo4jRepo, Init");
try {
Class.forName("org.neo4j.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:neo4j://localhost:7474/");
} catch (SQLException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
..
public boolean addDistanceUserListByForUserId(String userId) {
try {
final PreparedStatement ps = conn.prepareStatement( "create (n:User {name:{1}})" );
ps.setString( 1, "userId" );
ps.execute();
} catch (SQLException e) {
throw new RuntimeException(e);
}
return true;
}
谢谢,,
光线。使用
合并
而不是创建
:
"MERGE (n:User {name:{1}})"
[更新1]
以下示例说明如何修改addDistanceUserListByForUserId()
,以便返回包含已创建/现有用户的属性的映射
public Map<String, Object> addDistanceUserListByForUserId(String userId) {
try {
final PreparedStatement ps = conn.prepareStatement(
"MERGE (n:User {name:{1}}) RETURN n" );
ps.setString( 1, "userId" );
ResultSet rs = ps.executeQuery();
if (rs.next()) {
return (Map<String, Object>) rs.getObject("n");
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
return null;
}
以下是对该查询的解释:
- 它使用
可选匹配
,因此如果未找到具有指定的名称
的用户
,则不会跳过查询的其余部分(但n
将为NULL
)
- 然后创建一个
todo
集合,告诉FOREACH
子句是否应该创建新的User
节点。如果todo
集合为空,FOREACH
子句不执行任何操作
- 在修改子句(如
FOREACH
)和后续的MATCH
子句之间需要有一个WITH
子句。我们实际上不需要向前传递任何东西,所以我们只需要使用todo
,因为我们已经有了它
- 我们需要另一个
MATCH
查询,因为我们希望返回找到的节点或刚刚创建的节点。但是,除非我们进行另一次匹配,否则无法获取由FOREACH
创建的节点
您应该使用MERGE
而不是CREATE
。如果节点不存在,这将创建节点。如果节点已经存在,则合并
将像正常的匹配
操作一样工作
重要提示:在{}
属性语法中,应仅使用具有唯一约束的属性。Neo4j将合并{}
中具有相同属性的节点
如果合并后要在节点上设置其他数据,则:
合并(用户:用户{name:“John”,年龄:20})
-错误的方式。因为数据库中没有具有此类名称
和年龄
属性组合的节点,数据库将尝试创建该节点。这将导致约束冲突
,因为这样的名称
已经存在
正确版本:
MERGE (user:User {name: "John"})
SET user.age = 20
此版本将首先搜索节点(并在需要时创建),然后才在该节点上设置属性。如果您使用neo4J作为本地主机,则应注意neo4J embedded,因为它作为外部服务的性能更好。我们考虑将其嵌入。但是我们失去了GUI和其他东西。你认为嵌入式比ext好吗?嵌入式比fi好你在同一台服务器上:)可以使用嵌入式检索GUI:)如果我在进行远程操作,如何使用jdbc连接器按Id获取节点?知道如何映射它吗?永远不要使用nodeId作为数据,您应该添加自己的id属性,并使用约束将其设置为唯一。否则,您可以使用cypher(start n=node())通过其ID检索节点。请参阅我的更新答案。我还没有测试过该代码,但它似乎应该可以工作。这可以工作,但我对name使用了唯一的约束,并且我还有另一个名为age的属性。所以,如果用户已经存在,但具有不同的名称,并且我尝试合并,则会出现以下异常:执行cypher语句时出错[{code=Neo.ClientError.Schema.ConstraintViolation,message=Node 15已经存在,标签为user,属性为“name”=[Jossef]}]我已经更新了我的答案,并提出了一个建议,希望您能够解决您的约束问题。
MERGE (user:User {name: "John"})
SET user.age = 20