简化 Neo4j 查询,有条件地创建新关系

问题描述 投票:0回答:1

我有一个包含 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 盒子在一段时间后崩溃并出现“内存不足”异常。

因此,除了我不知道我的查询是否真正执行了我想要的操作(它在完成之前崩溃)之外,问题是:

我可以简化它以使其能够满足较小的内存需求吗?改进后的查询会是什么样子?

谢谢

database graph neo4j cypher
1个回答
4
投票
  1. 标准的 Neo4j 命名约定是使用驼峰式的标签名称和全大写的关系名称(并且属性应以小写字符开头)。在这个答案中,我将遵循标准并使用像
    Person
    MANAGES
    这样的名称。
  2. 如果关系本质上是双向的,则在相同的 2 个
    COMPETES_WITH
    节点之间不需要 2 个
    Person
    关系。 Neo4j 可以同样轻松地导航传入和传出关系,并且
    MATCH
    子句允许关系模式不指定方向(例如,
    MATCH (a)-[:FOO]-(b)
    )。此外,
    MERGE
    子句(但不是
    CREATE
    )允许您指定无向关系——这确保两个端点之间只存在一种关系。
  3. 看起来
    COMPETES_WITH
    关系确实属于
    Company
    节点之间,因为这确实是竞争的根源。此外,如果
    Person
    离开了公司,您不必从该节点中删除任何
    COMPETES_WITH
    关系(并且您也不应该向替换的
    COMPETES_WITH
    添加
    Person
    关系)。
  4. 此外,你首先应该考虑
    COMPETES_WITH
    关系是否真的需要。每当
    Company
    寻求的技能发生变化时,您就必须重新计算其
    COMPETES_WITH
    关系。您应该确定这样做是否值得,或者您的查询是否应该根据需要动态确定公司的竞争对手。
  5. 这是原始查询的简化版本:

    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;
    
  6. 如果您将数据模型更改为在

    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;
    
  7. 如果您根本没有

    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;
    
© www.soinside.com 2019 - 2024. All rights reserved.