为什么通过CREATE或MERGE查询在Neo4j中创建多个节点

时间:2018-05-19 18:59:17

标签: graph neo4j cypher graph-databases cypher-3.1

我正在使用CypherNeo4j中创建一些数据。这是一个非常直接的产品模型,具有以下元素

  1. 产品(例如手机)
  2. 功能(例如快速充电)
  3. 相关产品(例如篡改玻璃)
  4. 奥特莱斯(例如当地商店,相关产品通过网点销售)
  5. 我写了一些查询来插入数据。 尝试做什么

    • 创建产品
    • 创建功能集
    • 将产品与功能[:HAS_FEATURES]
    • 相关联
    • 创建网点x3
    • 创建相关产品1
    • 将产品链接到相关产品[:HAS_RP],并将相关产品链接到所有商店[:SOLD_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次,预计只会创建一次,就像第一个相关产品一样。

    任何人都可以帮助我理解我做错了什么吗?此外,以更好的方式编写查询的任何帮助都会很棒。

    enter image description here

2 个答案:

答案 0 :(得分:2)

问题出在这里:

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

您在3个节点之前创建了符合MATCH标准的节点:

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'})

因此,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)

答案 1 :(得分:0)

只需写一个@Christophe和@InverseFalcon已经回答/评论过的扩展名。正如resetting query cardinality中所述,此问题是由多次执行CREATE引起的。

每行执行查询。因此,当MERGE后跟WITH DISTINCT时,根据匹配结果,CREATE语句可能会多次执行并创建多个数据副本(除非存在唯一/节点键约束)最初只打算创建一次。

//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) 可以帮助解决问题,因为它不会创建多个副本,但MERGE仍然会执行多次。

这可以通过"使用from flask import Flask app = Flask(__name__) import os my_config = app.config.from_pyfile(os.path.join('.', 'config/app.conf'), silent=False) @app.route('/') def hello_world(): with app.open_instance_resource('app.cfg') as f: print(type(f.read())) return 'Hello World! {}'.format(app.config.get('LOGGING')) if __name__ == '__main__': app.run() 重置查询基数" 来处理。下面显示了解决问题的更新查询,图中显示了新结果。

myvar1="tester"
myvar2="tester"
myvar3="tester"

enter image description here

由于我对此很陌生,如果有人能够通过更好的书面查询展示如何更好地处理整个情况,那就会有所帮助。