您的查询失败是因为您要求 Neo4j 找到一个具有技能的人,即同时具有至少 3 个技能。显然,给定技能 n,它永远不会是 java 和 mysql 和 html。 (我假设您正在使用 contains 来“剥离”他们可能添加到技能名称中的任何版本信息,例如 javaee 或 java 8。请记住,这也将匹配 javascript。我建议您将这些数据导入 Neo4j,以让它将通用名称解析为单独的字段。如果您将名称视为技能数组,那么您可能没有匹配项,并且您的方案太脆弱而无法做任何有用的事情)
我会推荐这种匹配模式,以便 Neo4j 检查任何有效的技能节点
MATCH (n:Skill)<--(n1:PannaResume)
WITH n1, COLLECT(n.name) as skills
WHERE ANY(name in skills WHERE name contains "html")
AND (ANY(name in skills WHERE name contains "java")
OR ANY(name in skills WHERE name contains "mysql")
)
OR (
(ANY(name in skills WHERE name contains "c")
OR ANY(name in skills WHERE name contains "mssql")
))
当然,越明确越好。这会表现得更好。
MATCH (n1:PannaResume)-[:has_skill]->(:Skill {name : "html"})
WHERE ((n1)-[:has_skill]->(:Skill {name : "java"}) AND (n1)-[:has_skill]->(:Skill {name : "mysql"}))
OR ((n1)-[:has_skill]->(:Skill {name : "c"}) AND (n1)-[:has_skill]->(:Skill {name : "mssql"}))
RETURN n1
但您也可以通过将查询分成一组不同的查询并像这样合并结果来简化一点(并在 Cypher 规划器上使其更容易)
MATCH (n1:PannaResume)-[:has_skill]->(:Skill {name : "html"})
WHERE (n1)-[:has_skill]->(:Skill {name : "java"})
AND (n1)-[:has_skill]->(:Skill {name : "mysql"})
RETURN n1
UNION
MATCH (n1:PannaResume)-[:has_skill]->(:Skill {name : "html"})
WHERE (n1)-[:has_skill]->(:Skill {name : "c"})
AND (n1)-[:has_skill]->(:Skill {name : "mssql"})
RETURN n1
这应该等同于之前的查询,但可能更高效,具体取决于您正在做什么/Neo4j 版本。 WITH 会将查询分解为不同的阶段,因此会强制 Cypher 规划器先找到技能节点,然后再找到与这些技能相关的人员。
MATCH (html:Skill {name : "html"}), (java:Skill {name : "java"}), (c:Skill {name : "c"}), (mysql:Skill {name : "mysql"}), (mssql:Skill {name : "mssql"})
WITH *
MATCH (n1:PannaResume)-[:has_skill]->(html)
WHERE ((n1)-[:has_skill]->(java) AND (n1)-[:has_skill]->(mysql)
OR ((n1)-[:has_skill]->(c) AND (n1)-[:has_skill]->(mssql)
RETURN n1
如果您需要担心效率,您应该使用PROFILE 关键字尝试不同的查询。您尝试做的关键事情是最小化查询的每个“阶段”产生的行数,因为之后的每个阶段都将乘以前一阶段产生的行数。 (Cypher 计划器可以选择并行执行多个查询,然后找到它们的交集。因此,Cypher 的更改将如何影响计划并不明显。PROFILE 将显示您的查询效率低下,因此请注意以下步骤高 dbhits 或导致很多行。)