Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/neo4j/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Cypher-Neo4j查询评测_Neo4j_Cypher - Fatal编程技术网

Cypher-Neo4j查询评测

Cypher-Neo4j查询评测,neo4j,cypher,Neo4j,Cypher,我对Neo4j的查询分析有一些疑问。 考虑下面简单的CyfER查询: PROFILE MATCH (n:Consumer {mobileNumber: "yyyyyyyyy"}), (m:Consumer {mobileNumber: "xxxxxxxxxxx"}) WITH n,m MATCH (n)-[r:HAS_CONTACT]->(m) RETURN n,m,r; 输出为: 因此,根据: 3.7.2.2。扩展到 找到开始节点和结束节点后,展开为 用于查找两个

我对Neo4j的查询分析有一些疑问。 考虑下面简单的CyfER查询:

PROFILE 
MATCH (n:Consumer {mobileNumber: "yyyyyyyyy"}),
      (m:Consumer {mobileNumber: "xxxxxxxxxxx"}) 
WITH n,m 
MATCH (n)-[r:HAS_CONTACT]->(m) 
RETURN n,m,r;
输出为:

因此,根据:

3.7.2.2。扩展到

找到开始节点和结束节点后,展开为 用于查找两个节点之间的所有连接关系

询问

MATCH (p:Person { name: 'me' })-[:FRIENDS_WITH]->(fof)-->(p) RETURN
> fof
因此,在上面的查询中(在我的例子中),首先,它应该在找到任何关系之前找到StartNode和EndNode。但不幸的是,它只是找到StartNode,然后展开所有连接的
:HAS_CONTACT
关系,这导致不使用“expand Into”操作符。为什么会这样?只有一个
:两个节点之间有\u CONTACT
关系。在
:Consumer{mobileNumber}
上有一个唯一的索引约束。为什么上面的查询会扩展所有7个关系

另一个问题是关于过滤器操作符:为什么尽管已经检索到了所有节点/关系,但它仍需要12 db的命中率?为什么这个操作只需要6行12 db的调用

编辑 这是我查询的完整图形:

我还测试了上述相同查询的不同版本,但返回了相同的查询配置文件结果:

1. 2. 3.
为什么这样做?

这种行为似乎与查询计划器如何执行数据库搜索以响应您的密码查询有关。Cypher提供了一个在图形中搜索和执行操作的接口(可选方案包括JavaAPI等),查询由查询计划器处理,然后由neo4j的内部结构转换为图形操作。查询规划者将找到搜索图形最有效的方法(因此我们喜欢neo),这是有道理的。因此,仅仅因为一个密码查询是单向编写的,它不一定会以我们想象的方式搜索图形

关于这一点的文档似乎有点稀疏(或者说,我找不到合适的文档),任何链接或进一步的解释都将不胜感激

检查你的问题,我想你是想说:

“使用
mobileNumber
索引查找两个节点,每个节点都有
:Consumer
标签n和m,联系人号码分别为x和y。如果找到它们,请尝试查找
-[:HAS\u contact]->
n
m
的关系。如果找到该关系,请同时返回节点和关系,否则不返回任何内容。”

以这种方式运行此查询需要创建笛卡尔乘积(即,一个包含
n
m
所有组合的小表-在这种情况下,只有一行-但对于其他查询,可能会有更多行),然后搜索这些行之间的关系

而不是这样做,因为必须满足
MATCH
子句才能继续查询,neo知道如果查询要返回任何内容,那么两个节点
n
m
必须通过
-[:HAS_CONTACT]>
关系连接。因此,运行查询(并避免笛卡尔积)的最有效方法如下所示,这就是您的查询可以简化为的方法

“查找带有
:Consumer
标签的节点
n
,以及通过
-[:HAS\u CONTACT]连接的索引
mobileNumber
的值x。”->
relationshop到带有
:Consumer
标签的节点
m
,值y表示其适当性
mobileNumber
。返回两个节点和关系,否则不返回任何内容。”

因此,neo没有执行两个索引搜索,一个笛卡尔积和一组展开操作,而是只执行一个索引搜索、一个全部展开和一个过滤器

通过查询配置文件中的
AUTOSTRING
参数,您可以看到查询计划器简化的结果

如何更改查询以根据需要实现搜索

如果要更改查询,使其必须使用扩展到关系,请将该关系的要求设置为可选,或者使用显式迭代执行。下面的两个查询都将生成最初预期的查询配置文件

可选示例:

PROFILE
 MATCH (n:Consumer{mobileNumber: "xxx"})
 MATCH (m:Consumer{mobileNumber: "yyy"}) 
 WITH n,m 
 OPTIONAL MATCH (n)-[r:HAS_CONTACT]->(m) 
 RETURN n,m,r;
迭代示例:

PROFILE
 MATCH (n1:Consumer{mobileNumber: "xxx"})
 MATCH (m:Consumer{mobileNumber: "yyy"}) 
 UNWIND COLLECT(n1) AS n
 MATCH (n)-[r:HAS_CONTACT]->(m) 
 RETURN n,m,r;

您正在执行的查询与Neo4j文档中为扩展到提供的示例不同。示例查询在同一节点开始和结束

如果希望规划器首先找到两个节点并查看是否存在关系,则可以使用长度为1的
shortestPath
,以最小化数据库命中

PROFILE 
MATCH (n:Consumer {mobileNumber: "yyyyyyyyy"}),
  (m:Consumer {mobileNumber: "xxxxxxxxxxx"}) 
WITH n,m 
MATCH Path=shortestPath((n)-[r:HAS_CONTACT*1]->(m))
RETURN n,m,r;

你能在这里发布一些数据让我们更好地理解你的图表吗?这可能与查询规划者试图减少通过生成笛卡尔乘积(即,在第一个匹配子句中)而产生的负载有关,这是基于经验的一点猜测。您是否尝试过将查询的第一部分更改为使用两个
MATCH
子句,而不是一个带有逗号的子句?@DomWeldon请检查更新的问题谢谢您的回答。至于扩展到,根据文档,“当开始和结束节点都已找到时,扩展到用于查找两个节点之间的所有连接关系。”因此,我认为无论开始和结束节点是否相同,只要在扩展之前找到它们就行了,不是吗?我也读过这篇文章。我只能期望它被误解了。如果您创建的数据集支持示例中的查询(即循环),则它将使用展开到。感谢您的解释。但在这里我不能使用可选匹配,因为我只想在两个节点之间存在给定关系的情况下返回endNode+希望在扩展所有关系之前找到endNode以消除不必要的关系
PROFILE
 MATCH (n:Consumer{mobileNumber: "xxx"})
 MATCH (m:Consumer{mobileNumber: "yyy"}) 
 WITH n,m 
 OPTIONAL MATCH (n)-[r:HAS_CONTACT]->(m) 
 RETURN n,m,r;
PROFILE
 MATCH (n1:Consumer{mobileNumber: "xxx"})
 MATCH (m:Consumer{mobileNumber: "yyy"}) 
 UNWIND COLLECT(n1) AS n
 MATCH (n)-[r:HAS_CONTACT]->(m) 
 RETURN n,m,r;
PROFILE 
MATCH (n:Consumer {mobileNumber: "yyyyyyyyy"}),
  (m:Consumer {mobileNumber: "xxxxxxxxxxx"}) 
WITH n,m 
MATCH Path=shortestPath((n)-[r:HAS_CONTACT*1]->(m))
RETURN n,m,r;