1

Cypher用来在Neo4j. 这是一个非常简单的产品模型,具有以下元素

  1. 产品(例如手机)
  2. 功能(例如快速充电)
  3. 相关产品(例如钢化玻璃)
  4. 奥特莱斯(例如本地商店,相关产品通过奥特莱斯销售)

我写了一些查询来插入数据。它试图做的是

  • 创建产品
  • 创建功能集
  • 将产品与功能 [: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 次,而预计它只会被创建一次,就像第一个相关产品一样。

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

在此处输入图像描述

4

2 回答 2

2

问题位于此处:

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

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

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)
于 2018-05-19T20:46:46.460 回答
0

只需为 @Christophe 和 @InverseFalcon 已经回答/评论的内容编写扩展。如重置查询基数中所述,此问题是由CREATE多次执行引起的。

Queries execute per row. So, when a MATCH is followed by a CREATE, based on the match results, the CREATE statement might get executed multiple times and create multiple copies of data (unless unique/node key constraints are there) which was originally intended to be created only once.

MERGE can help with the issues since it'll not create multiple copies, but the MERGE is still executed multiple times.

This can be handled by "resetting query cardinality" using WITH DISTINCT. Below shows an updated query that solves the issue, and the figure shows the new results.

//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)

在此处输入图像描述

Since I'm new to this, if someone can show how the whole situation can be handled better with better written queries, that'll help.

于 2018-05-20T10:39:37.947 回答