我有2个帐户节点和几个列表节点,如下所示。 Match语句导致显示2个帐户,其中包含与该帐户关联的每个列表的关系。
我想要做的是根据每个共享相同电话号码的至少一个列表在两个账户之间建立关系。
如果可能的话,我希望看到所绘制的两个帐户节点之间的关系以及两个列表之间的关系,只要这些列表来自不同的帐户。
MERGE (:Account {account_id:11})
MERGE (:Listing {account_id:11, listing_id:1001, phone:99468320, author:'Paul'})
MERGE (:Account {account_id:12})
MERGE (:Listing {account_id:12, listing_id:1002, phone:97412521, author:'Sam'})
MERGE (:Listing {account_id:12, listing_id:1003, phone:97412521, author:'Sam'})
MERGE (:Listing {account_id:12, listing_id:1004, phone:99468320, author:'Sam'})
MERGE (:Listing {account_id:12, listing_id:1004, phone:0, author:'Same'})
MATCH (a:Account),(l:Listing)
WHERE a.account_id = l.account_id
CREATE (a)-[:LISTING]->(l)
RETURN a,l;
对于后者我确实尝试了以下但它有点疯狂,因为它将每个列表相互关联,具有相同的数字,只有在account_id不同时才这样做。
match (p1:Listing)
with p1
match (p2:Listing)
where p2.phone = p1.phone and p1 <> p2
merge(p1)-[r:SHARED_PHONE]-(p2)
RETURN p1, p2
首先,您应该仔细考虑是否真的需要SHARED_PHONE
关系,因为每次添加,删除或更改电话号码时都必须更新关系。这可能会使您的许多查询复杂化并使您的数据库不必要地变慢。此外,你最终可能会有很多SHARED_PHONE
关系(你可能不需要)。您可以考虑将具有相同电话号码的节点发现并入相关查询,而不是创建关系。
但是,如果你确定你真的需要这种关系,这里有一种方法可以做你想要的:
[更新]
MATCH (n: Listing)
WITH n.phone AS phone, COLLECT(n) AS ns
FOREACH(i IN RANGE(0, SIZE(ns)-2) |
FOREACH(x IN [ns[i]] |
FOREACH(y IN [z IN ns[i+1..] WHERE x.account_id <> z.account_id] |
MERGE (x)-[:SHARED_PHONE]-(y)
)))
WITH
子句收集共享相同Listing
的所有(唯一)phone
节点,并且嵌套的FOREACH
子句执行所需的最小数量的MERGE
s,以确保所有适当的节点通过SHARED_PHONE
关系(在任一方向上)连接。最里面的FOREACH
还确保要连接的节点不具有相同的account_id
。