我有一个包含 3 种类型的节点和两种关系的图形数据库:
(p:PERSON)-[:manages]->(c:COMPANY)-[:seeks]->(s:SKILLS)
我想在标记的节点之间创建新的关系
(:PERSON)
如:
(p1:PERSON)-[:competes_with]->(p2:PERSON)
和
(p2:PERSON)-[:competes_with]->(p1:PERSON)
须遵守
p1.name <> p2.name
。
这样我就可以代表
(s:SKILLS)
所代表的各种市场中稀缺劳动力的竞争。
建立新关系
[:competes_with]
的条件是,2个不同的人员节点(:PERSON)
管理的公司寻求至少3个(:SKILLS)
资料,这些资料在这2家公司之间一致。
数量级为:
|(:PERSON)| = 6000
|(:COMPANY)| = 15000
|(:SKILLS)| = 95000
以我缓慢的方式,我所做的是:
MATCH (p1:PERSON)-[:manages]->(:COMPANY)-[:seeks]->(s:SKILLS)
WITH p1, collect(DISTINCT s.skill_names) AS p1_skills
MATCH (p2:PERSON)-[:manages]->(:COMPANY)-[:seeks]->(s:SKILLS)
WITH p1,p1_skills, p2, collect(DISTINCT s.skill_names) AS p2_skills
WHERE p1 <> p2
UNWIND p1_skills AS sought_skills
WITH p1,p2, sought_skills, reduce(com_skills=[], sought_skills IN p2_skills | com_skills + sought_skills) AS NCS
WHERE size(NCS) >= 3
MERGE(p1)-[competes_with]->(p2)
MERGE(p2)-[competes_with]->(p1)
考虑到问题的严重性,这会导致 14GB RAM 盒子在一段时间后崩溃并出现“内存不足”异常。
因此,除了我不知道我的查询是否真正执行了我想要的操作(它在完成之前崩溃)之外,问题是:
我可以简化它以使其能够满足较小的内存需求吗?改进后的查询会是什么样子?
谢谢
Person
和 MANAGES
这样的名称。COMPETES_WITH
节点之间不需要 2 个 Person
关系。 Neo4j 可以同样轻松地导航传入和传出关系,并且 MATCH
子句允许关系模式不指定方向(例如,MATCH (a)-[:FOO]-(b)
)。此外,MERGE
子句(但不是CREATE
)允许您指定无向关系——这确保两个端点之间只存在一种关系。COMPETES_WITH
关系确实属于Company
节点之间,因为这确实是竞争的根源。此外,如果 Person
离开了公司,您不必从该节点中删除任何 COMPETES_WITH
关系(并且您也不应该向替换的 COMPETES_WITH
添加 Person
关系)。COMPETES_WITH
关系是否真的需要。每当 Company
寻求的技能发生变化时,您就必须重新计算其 COMPETES_WITH
关系。您应该确定这样做是否值得,或者您的查询是否应该根据需要动态确定公司的竞争对手。这是原始查询的简化版本:
MATCH (p1:Person)-[:MANAGES]->(:Company)-[:SEEKS]->(s:Skills)<-[:SEEKS]-(:Company)<-[:MANAGES]-(p2:Person)
WITH p1, p2, COUNT(s) AS num_skills
WHERE num_skills >= 3
MERGE(p1)-[:COMPETES_WITH]-(p2);
查找与给定
Person
竞争的 Person
节点:
MATCH (p1:Person {id: 123})-[:COMPETES_WITH]-(p2:Person)
RETURN p1, COLLECT(p2) AS competing_people;
如果您将数据模型更改为在
COMPETES_WITH
节点之间具有 Company
关系:
MATCH (c1:Company)-[:SEEKS]->(s:Skills)<-[:SEEKS]-(c2:Company)
WITH c1, c2, COUNT(s) AS num_skills
WHERE num_skills >= 3
MERGE(c1)-[:COMPETES_WITH]-(c2);
使用此模型,找到与给定
Person
竞争的 Person
节点:
MATCH (p1:Person {id: 123})-[:MANAGES]->(:Company)-[:COMPETES_WITH]-(:Company)<-[:MANAGES]-(p2:Person)
RETURN p1, COLLECT(p2) AS competing_people;
如果您根本没有
COMPETES_WITH
关系,要查找与给定 Person
竞争的 Person
节点:
MATCH (p1:Person {id: 123})-[:MANAGES]->(:Company)-[:SEEKS]->(s:Skills)<-[:SEEKS]-(:Company)<-[:MANAGES]-(p2:Person)
WITH p1, p2, COUNT(s) AS num_skills
WHERE num_skills >= 3
RETURN p1, COLLECT(p2) AS competing_people;