Graph 为什么通过创建或合并查询在Neo4j中创建多个节点

Graph 为什么通过创建或合并查询在Neo4j中创建多个节点,graph,neo4j,cypher,graph-databases,cypher-3.1,Graph,Neo4j,Cypher,Graph Databases,Cypher 3.1,我正在使用Cypher在Neo4j中创建一些数据。这是一个非常直截了当的产品模型,包含以下元素 产品(如手机) 功能(例如快速充电) 相关产品(如篡改玻璃) 门店(如当地门店,通过门店销售相关产品) 我写了一些查询来插入数据。它试图做的是 创建产品 创建要素集 将产品与功能链接[:具有功能] 创建插座x3 创建相关产品1 将产品链接到相关产品[:HAS\u RP],并将相关产品链接到所有门店[:sall\u THROUGH] 创建相关产品2 将其链接到上述产品和销售点 下面是实际的查询 //

我正在使用
Cypher
Neo4j
中创建一些数据。这是一个非常直截了当的产品模型,包含以下元素

  • 产品(如手机)
  • 功能(例如快速充电)
  • 相关产品(如篡改玻璃)
  • 门店(如当地门店,通过门店销售相关产品)
  • 我写了一些查询来插入数据。它试图做的是

    • 创建产品
    • 创建要素集
    • 将产品与功能链接[:具有功能]
    • 创建插座x3
    • 创建相关产品1
    • 将产品链接到相关产品[:HAS\u RP],并将相关产品链接到所有门店[:sall\u THROUGH]
    • 创建相关产品2
    • 将其链接到上述产品和销售点
    下面是实际的查询

    //Product
    CREATE (p:Product {name: 'Cool Mobile YX Plus',
      key: 'MOB0001',
      version: 'X.1'
    }),
    
    //Features
    (f:Features {hasQuickCharge: true,
      isAvailable: true,
      hasVolte: false
    })
    
    MERGE (p) -[:HAS_FEATURES]-> (f)
    
    //Outlets (:Product level lookup)
    CREATE (o1:Outlet {productType: 'New', seller: 'National_Shops', prId: 'MOB0001'})
    CREATE (o2:Outlet {productType: 'New', seller: 'Local_Shops', prId: 'MOB0001'})
    CREATE (o3:Outlet {productType: 'New', seller: 'Online_Shops', prId: 'MOB0001'})
    
    //Related products
    CREATE (rps1:RPS {rpId: 'TGS1108',
      rpName: 'YX Plus Tampered Glass',
      price: 180.99
    })
    WITH rps1
    MATCH (ol1:Outlet {productType: 'New', prId: 'MOB0001'})
    MATCH (pr1:Product {key: 'MOB0001'})
    MERGE (pr1) -[:HAS_RP {typeName: 'Child'}]-> (rps1)
    MERGE (rps1) -[:SOLD_THROUGH]-> (ol1)
    
    CREATE (rps2:RPS {rpId: 'CVR0204',
      rpName: 'YX Plus back cover',
      price: 299.00
    })
    WITH rps2
    MATCH (ol2:Outlet {productType: 'New', prId: 'MOB0001'})
    MATCH (pr2:Product {key: 'MOB0001'})
    MERGE (pr2) -[:HAS_RP {typeName: 'ChargeFor'}]-> (rps2)
    MERGE (rps2) -[:SOLD_THROUGH]-> (ol2)
    
    现在的问题是,第二个相关产品被创建了3次,,与第一个相关产品一样,预期只创建一次

    谁能帮我理解我做错了什么?此外,以更好的方式编写查询的任何帮助都将非常有用


    问题在这里:

    
    匹配(ol1:Outlet{productType:'New',prId:'MOB0001'})
    

    在符合匹配条件的3个节点之前创建:

    
    创建(o1:Outlet{productType:'New',seller:'National_Shops',prId:'MOB0001'})
    创建(o2:Outlet{productType:'New',seller:'Local_Shops',prId:'MOB0001'})
    创建(o3:Outlet{productType:'New',seller:'Online_Shops',prId:'MOB0001'})
    

    因此,
    MATCH(ol1:Outlet{productType:'New',prId:'MOB0001'})
    将返回3行,对于每一行,它将执行查询的下一部分,这一部分的3倍:

    MATCH (pr2:Product {key: 'MOB0001'})
    MERGE (pr2) -[:HAS_RP {typeName: 'ChargeFor'}]-> (rps2)
    MERGE (rps2) -[:SOLD_THROUGH]-> (ol2)
    

    只是对@Christophe和@InverseFalcon已经回答/评论的内容进行了扩展。如中所述,此问题是由于多次执行
    CREATE
    造成的

    查询按行执行。因此,当一个
    MATCH
    后面跟着一个
    CREATE
    时,根据匹配结果,CREATE语句可能会执行多次,并创建多个数据副本(除非存在唯一/节点键约束),这些数据原本只打算创建一次

    MERGE
    可以帮助解决这些问题,因为它不会创建多个副本,但合并仍会执行多次

    这可以通过使用带DISTINCT的
    来“重置查询基数”来处理。下面显示了解决问题的更新查询,图中显示了新结果

    //Related products
    CREATE (rps1:RPS {rpId: 'TGS1108',
      rpName: 'YX Plus Tampered Glass',
      price: 180.99
    })
    WITH rps1
    MATCH (ol1:Outlet {productType: 'New', prId: 'MOB0001'}) //3 match
    MATCH (pr1:Product {key: 'MOB0001'})
    MERGE (pr1) -[:HAS_RP {typeName: 'Child'}]-> (rps1)
    MERGE (rps1) -[:SOLD_THROUGH]-> (ol1)
    
    //next part of query will execute 3 times
    
    //reset cardinality back to 1 with WITH DISTINCT
    WITH DISTINCT 1 AS ResetCardinality
    CREATE (rps2:RPS {rpId: 'CVR0204',
      rpName: 'YX Plus back cover',
      price: 299.00
    }) //now CREATE & following executes only once
    WITH rps2
    MATCH (ol2:Outlet {productType: 'New', prId: 'MOB0001'})
    MATCH (pr2:Product {key: 'MOB0001'})
    MERGE (pr2) -[:HAS_RP {typeName: 'ChargeFor'}]-> (rps2)
    MERGE (rps2) -[:SOLD_THROUGH]-> (ol2)
    


    由于我是新手,如果有人能展示如何通过更好的书面查询更好地处理整个情况,这将有所帮助。

    作为补充,这里有一篇关于查询不相关部分之间的知识库文章,如本例。嗨,Christophe,谢谢你的回答。我的困惑是,为什么这只发生在第二个查询(YX加上封底),而不是第一个查询(YX加上篡改玻璃)?例如,如果我删除第二个,第一个就可以了@啊,现在我明白了。谢谢你的链接。因此,并不是合并部分造成了问题(如链接中所述,这很重,但很有效),而是创建(YX加上封底)被触发了3次!