我有一个图表数据库,有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)
个人资料的公司,这些公司在两家公司之间重合。
数量级是:
|(:人)| = 6000
|(:公司)| = 15000
|(:技能)| = 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盒在一段时间内崩溃并且内存不足&#34;例外。 所以,除了我不知道我的查询是否真的符合我想要的事情(它在完成之前崩溃)之外,问题是:我可以简化这个以使其适用于更小的内存要求 ?改进的查询会是什么样的? Tx。
答案 0 :(得分:4)
Person
和MANAGES
等名称。COMPETES_WITH
节点之间不需要2 Person
个关系。 Neo4j可以同样轻松地导航传入和传出关系,MATCH
子句允许关系模式不指定方向(例如,MATCH (a)-[:FOO]-(b)
)。此外,MERGE
子句(但不是CREATE
)允许您指定无向关系 - 这可确保两个端点之间仅存在一个关系。COMPETES_WITH
关系确实属于Company
个节点,因为这确实是竞争的源头。此外,如果Person
离开了公司,则您不必从该节点中删除任何COMPETES_WITH
关系(并且您也不必为替换COMPETES_WITH
添加Person
关系。 1}})。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;