如何查询多个OR的Neo4j路径?

时间:2015-12-28 16:38:38

标签: neo4j

任何人都知道在Neo4j中查询多个路径的快捷方法吗?

让我说我的电影节点可以有一个我想要匹配的类型(这是伪代码)

MATCH
(m:Movie)<-[:TYPE]-(g:Genre { name:'action' }) 
OR
(m:Movie)<-[:TYPE]-(x:Genre)<-[:G_TYPE*1..3]-(g:Genre { name:'action' }) 

(m)-[:SUBGENRE]->(sg:SubGenre {name: 'comedy'})
OR
(m)-[:SUBGENRE]->(x)<-[:SUB_TYPE*1..3]-(sg:SubGenre {name: 'comedy'})

问题是,第一个&#34; m:电影&#34;要匹配的节点必须与指定的路径之一匹配,第二个SubGenre在第一个匹配时依赖。 我可以创建一个使用MATCH和WHERE工作的查询,但它真的很慢(使用20MB的小数据集时为30秒)。

问题是,我不知道如何在Neo4j中匹配OR与其他OR匹配的第一个结果。

如果我使用WHERE,那么我必须声明在任何语句中使用的所有节点,在初始MATCH中使查询变慢(因为你不能在WHERE中引入新节点)

任何人都知道解决这个问题的优雅方法吗?谢谢!

3 个答案:

答案 0 :(得分:1)

也许OPTIONAL MATCH clause可能对此有所帮助。 OPTIONAL MATCH beavior类似于MATCH语句,除了代替全有或无模式匹配方法之外,模式中与语句中特定模式不匹配的任何元素都绑定为null 。

例如,要匹配电影,其类型和可能的子类型:

OPTIONAL MATCH (m:Movie)-[:IS_GENRE]->(g:Genre)<-[:IS_SUBGENRE]-(sub:Genre)
WHERE m.title = "The Matrix"
RETURN m, g, sub

这将返回电影节点,流派节点,如果存在,则返回子流派。如果没有子流派,那么它将为sub返回null。您可以使用上面的可变长度路径以及OPTIONAL MATCH

答案 1 :(得分:1)

您可以尝试长度最小为0的可变长度路径:

MATCH
(m:Movie)<-[:TYPE|:SUBGENRE*0..4]-(g) 
WHERE g:Genre and g.name = 'action' OR g:SubGenre and g.name='comedy'

对于使用索引查找类型/子类型的查询,我建议使用UNION查询。

MATCH
(m:Movie)<-[:TYPE*0..4]-(g:Genre { name:'action' }) 
RETURN distinct m
UNION
(m:Movie)-[:SUBGENRE]->(x)<-[:SUB_TYPE*1..3]-(sg:SubGenre {name: 'comedy'})
RETURN distinct m

答案 2 :(得分:1)

[EDITED]

以下MATCH子句应与您的伪代码等效。为了提高效率,还有一个USING INDEX子句假设您在:SubGenre(name)上有第一个created an index。 (如果:Genre(name)节点比Genre个节点多,则可以使用SubGenre上的索引。)

MATCH
  (m:Movie)<-[:TYPE*0..4]-(g:Genre { name:'action' }),
  (m)-[:SUBGENRE]->()<-[:SUB_TYPE*0..3]-(sg:SubGenre { name: 'comedy' })
USING INDEX sg:SubGenre(name)

Here is a console显示某些示例数据的结果。