【问题标题】:How to use sub queries with multiple (different) columns returned如何使用返回多个(不同)列的子查询
【发布时间】:2014-04-01 21:52:31
【问题描述】:

我承认,我真的找不到一个足够好的标题。这会很困难,但我会尽力解释我的情况。

我遇到了一个问题,对我来说唯一可能的解决方案似乎是使用两个单独的密码查询,其中第一个查询的结果用于在第二个查询中启动匹配,以完成工作.我觉得我的问题是独一无二的,因为据我尝试,我似乎无法获得 WITH 或 UNION 子句来给我想要的结果。

我正在尝试做的是以下内容。

MATCH (n1)--(n2) WHERE n2.name="something" WITH n2
MATCH (n2)--(n3) WHERE n3.name="something_else" WITH n3 as to_be_returned, n3 as to_continue
MATCH (to_continue)--(n4) WHERE n4.name="something"
RETURN to_be_returned as FirstPartResults, n4 as SecondPartResults

我在这里要做的是,当我在前两场比赛结束时,我希望将 Neo4j 匹配的任何信息保留为单独的信息 (n3),同时继续前进并使用它来进行进一步的匹配以缩小到 n4,当它结束时,返回 n3 和 n4。但是,我发现 Neo4j 所做的是,它为 n4 提供了正确的结果,但 n3 的结果始终与 n4 相同 - 即,它与“to_be_returned”混淆,而我希望它继续与“to_continue”混淆并留下“to_be_returned”。

我希望在单个查询中完成此操作的原因是,如果我将其分解为两个单独的查询,我会尽量避免分页问题。

我还使用 UNION ALL 尝试了以下操作:

MATCH (n1)--(n2) WHERE n2.name="something" WITH n2
MATCH (n2)--(n3) WHERE n3.name="something_else"
RETURN n3.name as "to_be_returned"

UNION ALL

MATCH (n1)--(n2) WHERE n2.name="something" WITH n2
MATCH (n2)--(n3) WHERE n3.name="something_else" WITH n3
MATCH (n3)--(n4) WHERE n4.name="something"
RETURN n4 as SecondPartResults

这给了我以下错误:

All sub queries in an UNION must have the same column names

将列名更改为相同,在不使用 UNION 的情况下给出与原始查询完全相同的结果。

编辑

由于某种原因,我无法创建和共享控制台 URL,所以我只将 CREATE 语句与 MATCH 查询一起粘贴到此处。

create 
(_6:Crew  {name:"Neo"}),
(_7:Crew  {name:"Morpheus"}),
(_8:Crew  {name:"Trinity"}),
(_9:Crew:Matrix  {name:"Cypher"}),
(_10:Matrix  {name:"Agent Smith"}),
(_11:Matrix  {name:"The Architect"}),
(_12:USER  {name:"Sherlock Holmes"}),
(_13:USER  {name:"John Watson"}),
_6-[:KNOWS]->_7,
_6-[:LOVES]->_8,
_6-[:FRIENDS]->_13,
_7-[:KNOWS]->_8,
_7-[:KNOWS]->_9,
_8-[:FRIENDS]->_12,
_9-[:KNOWS]->_10,
_10-[:CODED_BY]->_11

MATCH (c1:Crew) WHERE c1.name="Morpheus" WITH c1 MATCH (c1)--(c2:Crew) WITH c2 AS to_be_returned, c2 AS to_continueMATCH (to_continue)--(u:USER) WHERE u.name="Sherlock Holmes" RETURN to_be_returned AS FirstPart, to_continue AS SecondPart;

第一部分和第二部分的结果是相同的。第一部分应该包含结果 Trinity 和 Neo,第二部分应该只有 Trinity。

【问题讨论】:

  • 这是一个console example,您能做类似的事情并解释您希望查询返回哪些数据吗?是OPTIONAL MATCH 之类的问题,即“第二部分”可能不匹配吗?或者你是什么意思“它与 to_be_returned 混淆”?
  • 你有更具体的例子吗?您可以使用 collect 将某些信息放入集合中,而无需更改语句的基数。将所有匹配语句合并为一个怎么样?还是先用名称查找您的节点,然后对它们进行(可选)匹配?
  • 我已经使用示例数据集和示例查询编辑了问题,这给了我错误的输出。希望现在会更清楚。 @jjaderberg 我不认为这是一个可选的匹配问题。 Michael Hunger 我曾尝试使用 collect(to_be_resturned) 但它会导致同样的问题。我没有尝试过您的其他建议,但我希望我的编辑会使查询更清晰。顺便说一句,感谢您花时间回复。欣赏!!

标签: cypher graph-databases neo4j


【解决方案1】:

您可以先收集匹配的c2并将该集合分配为“to_be_returned”,然后继续进一步匹配原始c2而不是别名“to_continue”

MATCH (c1:Crew) WHERE c1.name='Morpheus'
WITH c1
MATCH (c1)--(c2:Crew)
WITH collect(c2) AS to_be_returned
MATCH (c2)--(u:USER)
WHERE u.name='Sherlock Holmes'
RETURN to_be_returned AS FirstPart, collect(c2) AS SecondPart

【讨论】:

  • 感谢您的回答!首先它有效!但是有个小问题。最后,我希望能够对结果进行分页,即使用 SKIP 和 LIMIT。我了解到 SKIP、LIMIT 选项不能用于集合。那么,有什么方法可以让我将 to_be_returned 限制为某个数字并针对这些有限的结果运行查询的第二部分?
  • 我设法解决了我的分页问题。您的答案完美无缺!谢谢!我犯的错误是与 'WITH collect(c2)' 一起,我也分别继承了 'c2'。谢谢丽莎、贾德伯格和迈克尔!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-21
  • 1970-01-01
  • 2022-10-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多