Как объединить узлы одного сообщества с Cypher в Neo4j?

Есть граф, каждый из его узлов содержит свойство communityIdчтобы указать, к какому сообществу принадлежит узел. Узлы связаны с LINK отношения, которые содержат weight свойство.

Я хочу объединить эти узлы одного и того же сообщества в большой узел. Связи между этими большими узлами (также известными как сообщества) должны быть разумно синтезированы / объединены: weightсвойство ссылки должно быть добавлено на основе отдельных узлов в каждом сообществе, подключенных к другому. Необходимо соблюдать направление ссылки.

На графике результатов я увижу только подключенные узлы сообщества.

Ближайшая функция - Merge Nodes, функция apoc.refactor.mergeNodes(). Однако результатом я недоволен, потому что:

  • Проблема 1: Узлы сообщества результатов имеют самосвязь.
  • Проблема 2: веса ссылок не суммируются, хотя в документации это указано.

Проблема 1 может быть решена написанием еще одного Cypher для удаления ссылок на себя. Но проблема 2 может быть решена только при низкоуровневом доступе к Graph (например, mergeNodes() выше).

Есть ли какой-нибудь элегантный подход к получению желаемого графа (узлов сообщества) за один раз? Или, по крайней мере, проблему 2 нужно как-то исправить.

Воспроизводимость

График:

       CREATE (a:User {name: "A", communityId: 2}), (b:User {name: "B", communityId: 2}), (c:User {name: "C", communityId: 2}), (x:User {name: "X", communityId: 1}), (y:User {name: "Y", communityId: 1}), (z:User {name: "Z", communityId: 1}), (w:User {name: "W", communityId: 1}), (a)-[:LINK {weight: 1}]->(b), (b)-[:LINK {weight: 1}]->(c), (c)-[:LINK {weight: 1}]->(a), (b)-[:LINK {weight: 1}]->(z), (z)-[:LINK {weight: 1}]->(x), (z)-[:LINK {weight: 1}]->(w), (w)-[:LINK {weight: 1}]->(y), (y)-[:LINK {weight: 1}]->(x), (b)-[:LINK {weight: 1}]->(w)

Сайфер:

       MATCH (n:User)
WITH n.communityId AS communityId, COLLECT(n) AS nodes
CALL apoc.refactor.mergeNodes(nodes, {
    properties: {
        name: 'combine',
        communityId: 'discard',
        weight: 'combine'
    },
    mergeRels: true
})
YIELD node
RETURN node

Системные требования

  • Windows 8.1 x64
  • Neo4j Desktop v1.3.4 (Двигатель v4.1.1.)
  • APOC v4.1.0.2
  • Библиотека науки о данных Graph v1.3.2

1 ответ

Решение

Я не совсем уверен, почему APOC не объединяет отношения в вашем примере. Тем не менее, вот запрос Cypher, с которого можно начать:

       MATCH (n:User)-[r]->(v:User)
WHERE n.communityId <> v.communityId  // discard self loop
WITH n.communityId as comId1, v.communityId as comId2, sum(r.weight) as w
MERGE (su1:SuperUser {communityId: comId1})  // create or get merged node for n.communityId
MERGE (su2:SuperUser {communityId: comId2})  // create or get node for v.communityId
MERGE (su1)-[r:SUPER_LINK]->(su2)
ON CREATE SET r.weight = w  // set relationship weight when it is created
RETURN su1, su2, r

который создает следующие узлы и отношения:

Другие вопросы по тегам