使用WHERE过滤查询而不创建新标识符

时间:2014-12-07 19:50:00

标签: neo4j cypher

这是一个初学者的问题,基于neo4j在线培训。 (第二章:使用模式过滤)。

问题是关于与Gene Hackman合作的演员的查询,但不是在他与Robin Williams合作的时候。

他们的解决方案是:

MATCH (gene:Person {name:"Gene Hackman"})-[:ACTED_IN]->(movie),
      (other)-[:ACTED_IN]->(movie), 
      (robin:Person {name:"Robin Williams"}) 
WHERE NOT (robin)-[:ACTED_IN]->(movie)
RETURN DISTINCT other;

通过试图找出为什么真正需要带有新标识符的第3行,我尝试了以下片段,但没有成功。

MATCH (gene:Person)-[:ACTED_IN]->()<-[:ACTED_IN]-(other)
WHERE gene.name="Gene Hackman"
    AND other.name <> "Robin Williams"
RETURN DISTINCT other;

MATCH (gene:Person)-[:ACTED_IN]->()<-[:ACTED_IN]-(other)
WHERE gene.name="Gene Hackman"
    AND NOT "Robin Williams" IN other.name
RETURN DISTINCT other;

显然我错过了一些东西。 我很感激任何指针!

2 个答案:

答案 0 :(得分:3)

您的第一次尝试:

MATCH (gene:Person)-[:ACTED_IN]->()<-[:ACTED_IN]-(other)
WHERE gene.name="Gene Hackman"
AND other.name <> "Robin Williams"
RETURN DISTINCT other;

这将匹配Gene Hackman与Robin Williams合作过的所有演员,但这并不符合,但是当他还在你的简报的工作组件时。为了做到这一点,你将不得不绑定关系链的movie部分。要使用IN,您还必须使用WITH,因为Chrisophe举了一个例子:

MATCH (gene:Person{name:"Gene Hackman"})-[:ACTED_IN]->(movie:Movie)<-[:ACTED_IN]-(other)
WITH movie, COLLECT(other.name) AS costars
WHERE NOT "Robin Williams" in costars
RETURN movie, costars

不幸的是,现在你有一个由电影作为结果的演员姓名(字符串)的聚合集合,而不是一组不同的演员(节点)。为避免字符串/节点问题,您可以使用WITH来转发other而不是other.name。然后,您将使用WHERE NOT谓词而不是FILTER。您仍然需要做一些工作才能回到不同的节点集。

MATCH (gene:Person{name:"Gene Hackman"})-[:ACTED_IN]->(movie:Movie)<-[:ACTED_IN]-(other)
WITH movie, COLLECT(other) AS costars
WHERE NONE(costar IN costars WHERE costar.name = "Robin Williams")
RETURN movie, costars

我想问的是,为什么你不想绑定'robin'节点?索引命中并绑定变量很便宜并且允许Neo4J工作它想要如何工作,使用未绑定的字符串将导致与每个节点进行多次交互的成本(“你是罗宾威廉姆斯吗?”)。

答案 1 :(得分:1)

您给出的第二次尝试几乎是正确的,您误用了IN运算符。

IN用于验证集合中是否存在元素,或者other.name是字符串。

以下是IN的一个例子:

MATCH (n:Person) AS persons
WITH collect(persons.name) as names
WHERE NOT 'Gene Hackman' IN names
RETURN names

你可以试试这个:

MATCH (gene:Person)-[:ACTED_IN]->()<-[:ACTED_IN]-(other)
WHERE gene.name="Gene Hackman"
    AND NOT "Robin Williams" = other.name
RETURN DISTINCT other;

但是,您现在有一个很长的模式,将在数据库中查找。拥有多个准确的细分更具性能。在您的用例中,将会有一个全局图表查找,如果可能,应该避免使用。