Neo4j - 不知道如何改进密码查询

时间:2015-05-11 17:14:59

标签: neo4j cypher

我有这个查询返回非常快,0.5秒并返回所有303个预期的记录。注意:“Woka”在这里的意思是“书”。

MATCH (p:Publisher)-[r:PUBLISHED]->(w:Woka)<-[s:AUTHORED]-(a:Author),
(l:Language)-[t:USED]->(w:Woka)-[u:INCLUDED]->(b:Bisac) 
WHERE (a.author_name = 'Camus, Albert') 
RETURN w.woka_id as woka_id, p.publisher_name as publisher_name, w.woka_title as woka_title, a.author_name as author_name, l.language_name as language_name, b.bisac_code as bisac_code, b.bisac_value as bisac_value 
ORDER BY woka_id;

我想添加更多信息,例如说明。我在语言和描述以及描述和书籍(Woka)之间创建了描述节点并且创建了关系。 下面的查询将所有描述都返回为null,但仅返回60个记录而不是303.这是因为并非所有书籍都有描述。执行时间仍然可以,0.3秒。

MATCH (p:Publisher)-[r:PUBLISHED]->(w:Woka)<-[s:AUTHORED]-(a:Author), 
(l:Language)-[t:USED]->(w:Woka), (b:Bisac)<-[u:INCLUDED]-(w:Woka),
(d:Description)-[v:HAS_DESCRIPTION]-(w) 
WHERE (a.author_name = 'Camus, Albert') 
RETURN w.woka_id as woka_id, p.publisher_name as publisher_name, w.woka_title as woka_title, a.author_name as author_name, l.language_name as language_name, b.bisac_code as bisac_code, b.bisac_value as bisac_value, d.description as description 
ORDER BY woka_id;

但是我知道结果集中遗漏了一些记录,50和303之间的差异确实有描述。我使用OPTIONAL构建另一个查询,但是这个(如下所示)永远不会返回,永远运行。

MATCH (p:Publisher)-[r:PUBLISHED]->(w:Woka)<-[s:AUTHORED]-(a:Author),
 (l:Language)-[t:USED]->(w:Woka)-[u:INCLUDED]->(b:Bisac) 
OPTIONAL MATCH (d:Description)-[v:HAS_DESCRIPTION]-(w:Woka)-[:AUTHORED]-(a:Author)  
WHERE (a.author_name = 'Camus, Albert') 
RETURN w.woka_id as woka_id, p.publisher_name as publisher_name, w.woka_title as woka_title, a.author_name as author_name, l.language_name as language_name, b.bisac_code as bisac_code, b.bisac_value as bisac_value, d.description as description 
ORDER BY woka_id;

当303记录的原始结果集不存在时,不知道如何改进查询以获取存在的可选描述和空值?

3 个答案:

答案 0 :(得分:5)

我想我们前一段时间已经有了这次谈话。

你必须降低你的中间基数

在您的人际关系中使用路线

不要重复您已经解决的模式,例如

OPTIONAL MATCH (d:Description)-[v:HAS_DESCRIPTION]-(w:Woka)-[:AUTHORED]-(a:Author)

应该是

OPTIONAL MATCH (d:Description)-[v:HAS_DESCRIPTION]-(w)

如果您要匹配长路径,则可以在其间创建很多潜在匹配,对于每个这些行执行下一个匹配,如果他们创建多行,每行得到rows1*rows2*rows3

的乘法

所以你必须使用DISTINCT或其间的聚合来尽可能地降低基数。

只需使用DISTINCT一次,使用collect向您展示第一个示例。这里可能没有必要,但它只是为了演示,因为这个例子足够小。

MATCH (p:Publisher)-[r:PUBLISHED]->(w:Woka)<-[s:AUTHORED]-(a:Author)
WHERE (a.author_name = 'Camus, Albert') 
WITH DISTINCT w,a,p

MATCH (l:Language)-[t:USED]->(w)
WITH w,a,p, collect(l) as languages

MATCH (w)-[u:INCLUDED]->(b:Bisac) 
RETURN w.woka_id as woka_id, w.woka_title as woka_title, 
       p.publisher_name as publisher_name, 
       a.author_name as author_name, 
       [l in languages | l.language_name] as language_names, 
       b.bisac_code as bisac_code, b.bisac_value as bisac_value 
ORDER BY woka_id;

您正确使用OPTIONAL MATCH,但您必须再次考虑可能会增加额外的行数。

OPTIONAL MATCH的另一种选择是使用路径表达式和解构,例如,描述:

RETURN w.woka_id as woka_id, w.woka_title as woka_title, 
       [p in ()<-[:HAS_DESCRIPTION]-(w) | head(nodes(p)).description] as descriptions

答案 1 :(得分:3)

除了@ pablosaraiva的回复,请确保您有一个索引:作者和财产author_name

create index on :Author(author_name)

如果这和pablo的回复没有帮助,请发布您的查询的查询计划。请使用explain <myquery>(假设您>&gt; = 2.2)

答案 2 :(得分:2)

你可以尝试一下吗?

MATCH (p:Publisher)-[r:PUBLISHED]->(w:Woka)<-[s:AUTHORED]-(a:Author), (l:Language)-[t:USED]->(w)-[u:INCLUDED]->(b:Bisac) 
WHERE (a.author_name = 'Camus, Albert') 
WITH p,r,w,s,a,l,t,u,b
OPTIONAL MATCH (d:Description)-[v:HAS_DESCRIPTION]-(w)
RETURN w.woka_id as woka_id, p.publisher_name as publisher_name, w.woka_title as woka_title, a.author_name as author_name, l.language_name as language_name, b.bisac_code as bisac_code, b.bisac_value as bisac_value, d.description as description 
ORDER BY woka_id;