简体   繁体   English

Neo4j Cypher MATCH如果不存在

[英]Neo4j Cypher MATCH if Not exists

In SQL where is an option (NOT EXISTS) that allows us to only select a row if there is zero results from other SELECT. 在SQL中,这是一个选项(NOT EXISTS),它允许我们只在其他SELECT的结果为零时才选择一行。

For example: 例如:

SELECT 
    c.CustomerKey
FROM
    Customer c, Sales s1, Date d
WHERE
    s1.CustomerKey = c.CustomerKey AND
    s1.OrderDateKey = d.DateKey AND
    s1.ShipDate > s1.DueDate AND
    NOT EXISTS (SELECT *
                FROM Sales s2
                WHERE s2.OrderDateKey = s1.OrderDateKey AND
                      s2.CustomerKey <> s1.CustomerKey)
GROUP BY 
    c.CustomerKey

I tried to do the following but the query never ends so I assume I'm doing it the wrong way. 我尝试执行以下操作,但查询永远不会结束,所以我假设我做错了。 What am I missing? 我错过了什么?

MATCH (d1:Date)<-[:ORDERDATE]-(s1:Sales)-[:CUSTOMER]->(c1:Customer)
WHERE s1.ShipDate > s1.DueDate
WITH d1,s1,c1
MATCH (s2:Sales)-[:CUSTOMER]->(c2:Customer)
WHERE NOT(s2.OrderDateKey=s1.OrderDateKey AND c2.CustomerKey<>c1.CustomerKey)
RETURN c2.CustomerKey

The query below should do what you want. 下面的查询应该做你想要的。

First, you should create an index on :Sales(OrderDateKey) so that the OPTIONAL MATCH in the query below can quickly find the desired Sales nodes (instead of scanning all of them): 首先,您应该在:Sales(OrderDateKey)上创建索引,以便下面查询中的OPTIONAL MATCH可以快速找到所需的Sales节点(而不是扫描所有节点):

CREATE INDEX ON :Sales(OrderDateKey);

When the OPTIONAL MATCH clause fails to find a match, it sets its unbound identifiers to NULL . OPTIONAL MATCH子句无法找到匹配项时,它会将其未绑定标识符设置为NULL The following query takes advantage of that fact: 以下查询利用了这一事实:

MATCH (:Date)<-[:ORDERDATE]-(s1:Sales)-[:CUSTOMER]->(c1:Customer)
WHERE s1.ShipDate > s1.DueDate
WITH s1.OrderDateKey AS odk, c1.CustomerKey AS customerKey
OPTIONAL MATCH (s2:Sales)-[:CUSTOMER]->(c2:Customer)
WHERE s2.OrderDateKey=odk AND c2.CustomerKey<>customerKey
WITH customerKey
WHERE c2 IS NULL
RETURN DISTINCT customerKey;

The tricky part of translating SQL to Cypher is figuring out when we should still do joins and predicates based on keys, vs when we should be translating those operations into usages of nodes and relationships. 将SQL转换为Cypher的棘手部分是确定何时我们仍然应该基于密钥进行连接和谓词,以及何时应该将这些操作转换为节点和关系的用法。

Let's first translate what the SQL means, as best as I can tell: 让我们首先翻译SQL的含义,尽我所知:

We want to match a Sale with a Customer and an order Date, where the sale's ship date is past the due date, and there isn't already a Sale with the same order Date for a different Customer. 我们希望将销售与客户和订单日期相匹配,销售的发货日期超过截止日期,并且不存在具有相同订单的销售日期不同的客户。

It looks like Sale.OrderDateKey is a foreign key to Date.DateKey's primary key, and that Sales.CustomerKey is a foreign key to Customer.CustomerKey's primary key. 看起来像Sale.OrderDateKey是Date.DateKey的主键的外键,而Sales.CustomerKey是Customer.CustomerKey的主键的外键。

If the above assumption is true, then we don't need to work with these keys at all...where SQL uses foreign and primary keys for joining, Neo4j uses relationships between nodes instead, so we don't need to actually use these fields for anything in this query except the returned values. 如果上面的假设是正确的,那么我们根本不需要使用这些键......在SQL使用外键和主键进行连接的情况下,Neo4j使用节点之间的关系,所以我们不需要实际使用这些此查询中除返回值之外的任何字段。

MATCH (orderDate:Date)<-[:ORDERDATE]-(s1:Sales)-[:CUSTOMER]->(c1:Customer)
WHERE s1.ShipDate > s1.DueDate
WITH orderDate, c1
// match to exclude is a sale with the same orderDate but different customer
OPTIONAL MATCH (orderDate)<-[:ORDERDATE]-(:Sales)-[:CUSTOMER]->(c2:Customer)
WHERE c1 <> c2
WITH c1
WHERE c2 IS NULL
RETURN DISTINCT c1.customerKey;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM