Neo4j WHERE 基于数组的谓词与 EXISTS 和关系

问题描述 投票:0回答:1

我有一个

Vacancy
节点,它与
Country
相关(
Country
也有标签
Requirable
):

(v:Vacancy)-[:WORK_PERMIT_IN]-(:Country)

此外,

Vacancy
有一个非规范化属性
workCountryIds
,其中包含国家/地区的所有ID。

您能否建议就大型数据集的性能而言,哪种方法最适合在 Neo4j 中用于 WHERE 谓词:

MATCH  ( v:Vacancy )  
WHERE  ( coalesce(size(v.workCountryIds), 0) <= 0  OR  exists { MATCH (v)-[:WORK_PERMIT_IN]-(req3:Requirable) WHERE req3.id IN [11, 12, 13]}  )  
RETURN v

MATCH  ( v:Vacancy )  
WHERE ( NOT exists { MATCH (v)-[:WORK_PERMIT_IN]-(:Country)}  OR  exists { MATCH (v)-[:WORK_PERMIT_IN]-(req3:Requirable) WHERE req3.id IN [11, 12, 13]}  )
RETURN v

在第一种情况下,我使用:

coalesce(size(v.workCountryIds), 0) <= 0

第二个:

NOT exists { MATCH (v)-[:WORK_PERMIT_IN]-(:Country)}

这两种方法在性能方面使用哪种更好?

neo4j cypher query-optimization
1个回答
0
投票

您的第二种情况必须遵循每个

WORK_PERMIT_IN
Vacancy
关系,以检查另一端是否没有
Country
节点(在最坏的情况下,它必须检查每个这样的节点)。但是你的第一个案例只需要查看每个
Vacancy
节点的一个属性(完全忽略关系),所以它会更快。 [注意:如果
WORK_PERMIT_IN
关系 always 连接
Vacancy
Country
节点,那么通过将
(:Country)
更改为
()
,第二种情况会更快,并且您还应该使关系模式具有方向性。但即使进行了这些调整,第二种情况也会变慢。]

但是,实际上还存在另一个与性能有关的问题,并且在您的两种情况下都存在。我将用你的第一个案例来说明,因为那已经更快了。这是您的第一个案例(为了可读性而重新格式化):

MATCH (v:Vacancy)  
WHERE
  // (a)
  COALESCE(SIZE(v.workCountryIds), 0) <= 0 OR
  // (b)
  EXISTS {
    MATCH (v)-[:WORK_PERMIT_IN]-(req3:Requirable)
    WHERE req3.id IN [11, 12, 13]
  }
RETURN v

您返回的职位空缺是:(a) 未连接到任何

Country
,或 (b) 连接到一些所需的
Requirable
节点。 (b) 的实现效率很低,因为只要 (a) 不适用,它就会执行
MATCH (v)-[:WORK_PERMIT_IN]-(req3:Requirable)
,这可能是大多数
v
的情况。并且,假设有很多
Requirable
id,那么在几乎每个
MATCH
上执行该
v
而不是仅连接到 3 个所需
Requirable
节点的空位是非常浪费的。

这个查询应该更高效:

// (a)
MATCH (v1:Vacancy)
WHERE COALESCE(SIZE(v1.workCountryIds), 0) = 0
WITH COLLECT(v1) AS v1List
// (b)
MATCH (v2)-[:WORK_PERMIT_IN]->(req:Requirable)
WHERE req.id IN [11, 12, 13] AND NOT v2 IN v1List
WITH v1List, COLLECT(v2) AS v2Listrequired ids
// Return combined (a) and (b) results
RETURN v1List + v2List AS v
© www.soinside.com 2019 - 2024. All rights reserved.