查询比较CQL中的两个列表(Cypher)

时间:2016-07-08 19:00:21

标签: neo4j compare cypher

我在neo4j的图表数据库中有关于某些产品及其购买日期的数据

产品 1. A,B,C,D,E,F,G 购买日期为7月6日至8日

购买模式如下

7月6日 - A,B,C,D 7月7日 - A,B,C,D,E 7月8日 - A,B,D,E,F,G

购买日期作为订单节点中的属性存储。 (即o.purchase_date)

我写了一个Cypher查询来计算每天的购买次数

Match (o :Order)-[:Contains]->(p :Product) 
return o.purchase_date, count(p)

Output:
o.purchase_date       count(p)
6th July                   4
7th July                   5
8th July                   6

我想修改此信息以查询告诉我每天购买的新产品的总数与前一天相比。即7月7日7月8日8日

有什么建议吗?

2 个答案:

答案 0 :(得分:1)

我认为你会想要以不同的方式解决这个问题。操作必须使用前一行数据的查询很难组合在一起。刚刚达到可以同时从两个不同的行引用数据的难点,并且能够在每组两行之间执行相同的操作是另一个棘手的问题。

如果您的订单之间存在关系,就像每个升序之间的[:Next]之间的关系一样,那么问题的头痛就变得微不足道了。

以下查询没有订购,我会留给您,因为您的示例建议购买日期可能是字符串格式,不会按原样顺序排序。

MATCH (o1:Order)-[:Next]->(o2:Order)-[:Contains]->(p2:Product)
WHERE NOT (o1)-[:Contains]->(p2)
WITH o1, o2, COLLECT(p2) AS NewProds
RETURN o1, o2, NewProds, SIZE(NewProds) AS NewProdCnt

这将返回包含订单对的行,显示新产品和每个订单之间的新产品数量。如果您不需要,可以从退货中轻松删除o1和/或NewProds,这样只会按顺序为您提供订单和新产品的数量。

这里明显的缺点是缺少订单链的第一个(没有先前的订单)。

如果您需要,以下修改应解决此问题:

MATCH (o1:Order)-[:Next*0..1]->(o2:Order)-[:Contains]->(p2:Product)
WHERE (o1 = o2 AND NOT (:Order)-[:Next]->(o2) AND (o2)-[:Next]->(:Order)) 
OR NOT (o1)-[:Contains]->(p2)
WITH o1, o2, COLLECT(p2) AS NewProds
RETURN o1, o2, NewProds, SIZE(NewProds) AS NewProdCnt

:o1和o2之间的下一个关系现在是可选的,允许它在没有先前订单的订单上匹配,但是我们必须仅在没有先前订单时才计算(否则每个订单都可以与自己匹配) o1和o2,而不仅仅是链子开头的订单),它有助于添加一个附加条件,订单必须具有下一个订单。这意味着我们不会为单独的订单取回任何东西,如果:下一个关系只是临时的,或者在运行这种查询的某些订单之间即时创建(在完成时删除),这可能是合乎需要的。你不会想要接受你不感兴趣的任何其他订单。

最后,创造下一个关系的一切都是混乱的。 This article在使用neo4j中的链接列表方面有一些非常有趣的内容,但是现在与我们相关的部分看起来像这样(复制并粘贴在文章中):

...
WITH elem ORDER BY elem.name ASC
WITH COLLECT(elem) AS elems
FOREACH (n IN RANGE(0, LENGTH(elems)-2) |
  FOREACH (prec IN [elems[n]] |
    FOREACH (next IN [elems[n+1]] |
      MERGE prec-[:Next]->next)))

您应该使用自己的匹配和有兴趣订单的顺序替换开头和第一个WITH子句。您将收集它们并迭代该列表,创建它们之间的下一个关系。您当然可以使用不同的标签,特别是如果您已经拥有或计划使用:其他用例的订单之间的下一个关系(因为这会弄乱您的查询,并且在您完成时删除这些关系可能会意外摆脱与同一标签无关的关系。)

当我设置下一个关系时,我遇到了一个奇怪的事情:创建了指向同一节点的下一个关系。如果确实发生了这种情况,您将在以下情况下进行清理:创建下一个关系:

MATCH (a:Order)-[r:Next]->(a)
DELETE r

稍后,如果您的:下一个标签是临时的,您需要在获得所需数据后进行清理,只需删除所有:订单节点之间的下一个关系:

MATCH (:Order)-[r:Next]-(:Order)
DELETE r

答案 1 :(得分:0)

使用filter function比较列表:

WITH [ 'A', 'B', 'C', 'D']      as List1, 
     [ 'A', 'B', 'C', 'D', 'E'] as List2
RETURN FILTER ( product in List2 WHERE NOT product in List1 ) as newProduct

list comprehension

WITH [ 'A', 'B', 'C', 'D']      as List1, 
     [ 'A', 'B', 'C', 'D', 'E'] as List2
RETURN [product in List2 WHERE NOT product in List1] as newProduct