我有一个关于如何限制节点之间创建的关系数的问题。我肯定可以在执行MATCH时限制数量或产生的音符。但实际上,我更关心的是不存储数据(在这种情况下为关系)的想法,因为将来我将永远不会使用它。
在我的情况下,我有以下图形:
Jypiter notebooks
请注意,我有一个用户和10个不同的艺术家。
我的要求是存储用户通过CREATE (u:User {id: 100001}), (:Artist {id: "0001"}), (:Artist {id: "0002"}), (:Artist {id: "0003"}), (:Artist {id: "0004"}), (:Artist {id: "0005"}),(:Artist {id: "0006"}),(:Artist {id: "0007"}),(:Artist {id: "0008"}),(:Artist {id: "0009"}),(:Artist {id: "0010"});
关系收听的最近5位艺术家。因此,执行后:
LISTENED_TO
我会有一个像这样的图
MATCH (u:User {id: 100001}), (a:Artist {id: "0001"})
CREATE (u)-[:LISTENED_TO]->(a);
MATCH (u:User {id: 100001}), (a:Artist {id: "0003"})
CREATE (u)-[:LISTENED_TO]->(a);
MATCH (u:User {id: 100001}), (a:Artist {id: "0005"})
CREATE (u)-[:LISTENED_TO]->(a);
MATCH (u:User {id: 100001}), (a:Artist {id: "0007"})
CREATE (u)-[:LISTENED_TO]->(a);
MATCH (u:User {id: 100001}), (a:Artist {id: "0009"})
CREATE (u)-[:LISTENED_TO]->(a);
现在,我得到的信息是该用户已经听了5位不同的艺术家的音乐。现在让我们假设用户收听了来自艺术家{id:“ 0010”}的歌曲,我希望删除第一个插入的关系(u:User {id: 100001})-[l:LISTENED_TO]->(a:Artist {id: "0001"})
(u:User {id: 100001})-[l:LISTENED_TO]->(a:Artist {id: "0003"})
(u:User {id: 100001})-[l:LISTENED_TO]->(a:Artist {id: "0005"})
(u:User {id: 100001})-[l:LISTENED_TO]->(a:Artist {id: "0007"})
(u:User {id: 100001})-[l:LISTENED_TO]->(a:Artist {id: "0009"})
(例如使用类似FIFO的机制),并删除新的图就像:
(u:User {id: 100001})-[l:LISTENED_TO]->(a:Artist {id: "0001"})
也许我正在扩展Neo4J支持的功能,但是我想知道这是否可能。我的目标是节省不需要存储的空间,因为我只需要最近使用的(在这种情况下为听众)最近的5位艺术家即可。
答案 0 :(得分:1)
如果LISTENED_TO
关系在time
属性中包含时间戳,那么在添加新关系时,您可以使用该关系仅保留5个最新关系(假设新关系的时间戳)总是足够近,并且您通过了userId
,artistId
和time
parameters):
MATCH (u:User {id: $userId})
OPTIONAL MATCH (u)-[lt:LISTENED_TO]->(:Artist)
WITH u, lt ORDER BY lt.time DESC
WITH u, COLLECT(lt) AS lts
FOREACH(x IN lts[4..] | DELETE x)
MERGE (a:Artist {id: $artistId})
CREATE (u)-[:LISTENED_TO {time: $time}]->(a)
[更新]
注意:如果该用户最近多次收听同一位艺术家,则上述查询允许该位艺术家与该用户具有多种关系。
如果您希望某个艺术家与特定用户最多具有一种关系,则此更复杂的查询应该可以工作:
MATCH (u:User {id: $userId})
OPTIONAL MATCH p= (u)-[lt:LISTENED_TO]->(a:Artist)
WITH u, {lt: lt, a: a} AS data ORDER BY lt.time DESC
WITH u, REDUCE(
s = {cnt: 0, del: []}, x IN COLLECT(data) |
CASE WHEN x.a.id = $artistId OR s.cnt = 4
THEN {cnt:s.cnt, del:s.del + x.lt}
ELSE {cnt:s.cnt + 1, del:s.del} END).del AS del
FOREACH(x IN del | DELETE x)
MERGE (a:Artist {id: $artistId})
CREATE (u)-[:LISTENED_TO {time: $time}]->(a)