Сайфер: правила игры наследования - PullRequest
0 голосов
/ 09 октября 2019

У нас есть узлы, организованные в виде дерева (((: Object) - [: PARENT] -> (: Object))
Объект может использовать множество Item ({: Object) - [: USE] -> (: Item))

Мы бы хотели воспроизвести правило наследования:
если родитель использует один элемент, а у сына нет элемента с такими же свойствами => сын будет использовать элемент родителя.

Следующий код работает нормально, но очень медленно работает на больших наборах (у нас есть около 4 тыс. Объектов, у объекта может быть 2 тыс. Использования)

MATCH (p:Object)
WHERE p.rank = 1
WITH p
MATCH (p)-[:PARENT]->()-[:USE]->(used)
WHERE NOT exists((p)-[:USE]->(:Item {
                        property1:used.property1,
                        property2:used.property2,
                        property3:used.property3}))
MERGE (p)-[:USE]->(used);

У вас есть лучшее решение?

- ОБНОВЛЕНИЕ -

После изучения кажется, что медлительность связана с размером транзакции (мы добавляем несколько миллионов отношений).
Итак, мы сейчас ищем способразделить транзакцию, чтобы получить что-то вроде этого:

DO {
    MATCH (p:Object)
    WHERE p.rank = 1 AND p.updated IS null
    WITH p LIMIT 50
    MATCH (p)-[:PARENT]->()-[:USE]->(item)
    WHERE NOT exists((p)-[:USE]->(:Item {
                        property1:item.property1,
                        property2:item.property2,
                        property3:item.property3}))
    MERGE (p)-[:USE]->(item)
    SET p.updated=true

    COMMIT
} WHILE(something updated)

В настоящее время мы нашли единственный способ сделать внешние сценарии (powershell или python).
Возможно ли это сделать в Cypher?

1 Ответ

0 голосов
/ 09 октября 2019

[ОБНОВЛЕНО]

Вместо миллионов дополнительных отношений вы можете вместо этого запрашивать унаследованные свойства элемента при необходимости.

Например, чтобы запустить запрос для Object 123 (чтонеобходимо учитывать унаследованные свойства):

MATCH (p:Object)
WHERE p.id = 123
MATCH path=(p)-[:PARENT*0..]->()-[:USE]->(used)
WITH p, used
ORDER BY LENGTH(path) DESC
WITH p, REDUCE(t = x, x IN COLLECT(used) | apoc.map.merge(t, PROPERTIES(v))) AS used
...

Кстати, вам все равно понадобится та же логика, даже если у вас были дополнительные отношения, о которых вы изначально просили.

Примечание. Этот алгоритм (который сортируется по убыванию длины path) работает правильно только в том случае, если существует один листовой предок и единственный путь к этому предку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...