如何给可能不存在的节点添加关联?connectOrCreate及MERGE用法咨询
实现方案说明
核心问题解答
你提到的「添加User和Vote关联时,若Vote不存在则先创建再关联」的需求是完全可以实现的,不需要额外调用顶层createVotes mutation,以下是两种可行的实现思路:
方案1:使用Cypher MERGE 语句实现(无需自定义拼接ID)
直接通过关联关系匹配对应的Vote节点,不存在时自动创建节点和对应关联边,示例代码如下:
// 先匹配到指定的Topic、Detail、User节点 MATCH (t:Topic {id: $topicId}), (d:Detail {id: $detailId}), (u:User {id: $userId}) // 匹配同时关联了当前Topic和Detail的Vote节点,不存在则创建节点和两条关联边 MERGE (t)<-[:VOTE_HAS_THING]-(v:Vote)-[:VOTE_HAS_FACT]->(d) // 匹配用户和Vote的VOTED关系,不存在则创建关联 MERGE (u)-[:VOTED]->(v) RETURN v
该方案优势是无需额外处理ID逻辑,适合数据量不大的场景。
方案2:使用connectOrCreate GraphQL mutation实现
你可以直接在更新User的mutation中嵌套connectOrCreate逻辑,不需要单独调用createVotes,示例代码如下:
mutation AddUserVote($userId: ID!, $topicId: ID!, $detailId: ID!) { updateUsers( where: { id: $userId } connect: { VOTED: { Vote: { connectOrCreate: { where: { node: { VOTE_HAS_THING: { Topic: { id: $topicId } }, VOTE_HAS_FACT: { Detail: { id: $detailId } } } } onCreate: { node: { # 此处可填写Vote节点的其他默认属性,比如创建时间、初始票数等 VOTE_HAS_THING: { connect: { Topic: { id: $topicId } } }, VOTE_HAS_FACT: { connect: { Detail: { id: $detailId } } } } } } } } } ) { users { id VOTED { id } } } }
关于Vote节点ID设置的建议
- 如果你的Vote节点量级较大,推荐使用
Topic.id拼接Detail.id作为Vote的唯一ID,匹配时直接通过ID查询,不需要遍历两层关联边,查询性能会有明显提升,实现逻辑也更简单可控。 - 如果当前数据量较小,优先考虑开发简便,可以不用设置拼接ID,直接用上述关联匹配方案即可正常运行。
内容的提问来源于stack exchange,提问作者Thingamajig
相关产品推荐
相关产品推荐

