Добавление случайных отношений в Neo4j использует только один узел - PullRequest
1 голос
/ 07 июля 2019

Моя структура выглядит следующим образом:

Person   -[:HAS_HOBBY]->  Hobby

Я генерирую, например, 500 человек-узлов и 20 хобби-узлов случайным образом, и теперь хотел бы генерировать случайные связи между ними, чтобы у каждого человека было 1 или болеехобби, но не у каждого человека один и тот же.

CALL apoc.periodic.iterate("
    match (p:Person),(h:Hobby) with p,h limit 1000 
    where rand() < 0.1 RETURN p,h ", 
    "CREATE (p)-[:HAS_HOBBY]->(h)", 
    {batchSize: 20000, parallel: true}) 
YIELD batches, total 
RETURN *

Без функции APOC запрос выглядит так:

MATCH(p:Person),(h:Hobby)
WITH p,h
LIMIT 10000
WHERE rand() < 0.1
CREATE (p)-[:HAS_HOBBY]->(h)

Это запрос, который я пробовал, проблема в том, чтовсе узлы человека все связаны с одним узлом хобби, поэтому используются только 1/20 узлов.

Чего-то не хватает в моем запросе?Или я должен решить эту проблему по-другому?

Я также пробовал разные подходы с предложениями FOREACH, проходящими через все узлы или использующими SKIP и LIMIT через декартово произведение

Большое спасибо!

edit:

Запрос от InverseFalcon с использованием apoc.periodic.iterate:

call apoc.periodic.iterate("
// first generate your range of how many hobbies you want a person to have
// for this example, 1 to 5 hobbies
WITH range(1,5) as hobbiesRange
// next get all hobies in a list
MATCH (h:Hobby)
WITH collect(h) as hobbies, hobbiesRange
MATCH (p:Person)
// randomly pick number of hobbies in the range, use that to get a number of random hobbies
WITH p, apoc.coll.randomItems(hobbies, apoc.coll.randomItem(hobbiesRange)) as hobbies
// create relationships
    RETURN p,hobbies", 
"FOREACH (hobby in hobbies | CREATE (p)-[:HAS_HOBBY]->(hobby))", 
{batchSize: 1000, parallel: false});

Ответы [ 2 ]

1 голос
/ 08 июля 2019

В этом случае было бы проще не использовать iterate (), а вместо этого использовать некоторые вспомогательные функции коллекции APOC, например, используемые для получения случайных элементов из коллекции. Примерно так:

// first generate your range of how many hobbies you want a person to have
// for this example, 1 to 5 hobbies
WITH range(1,5) as hobbiesRange
// next get all hobies in a list
MATCH (h:Hobby)
WITH collect(h) as hobbies, hobbiesRange
MATCH (p:Person)
// randomly pick number of hobbies in the range, use that to get a number of random hobbies
WITH p, apoc.coll.randomItems(hobbies, apoc.coll.randomItem(hobbiesRange)) as hobbies
// create relationships
FOREACH (hobby in hobbies | CREATE (p)-[:HAS_HOBBY]->(hobby))
0 голосов
/ 07 июля 2019

Ваш запрос правильный, за исключением ограничения, оно должно быть 10000 вместо 1000. (Лучше не используйте ограничение).Это работает для меня и создает почти 1000 отношений (случайный человек и хобби) для 500 человек и 20 хобби.

Если вы использовали это для выполнения этой операции в пакетах, тогда установите размер пакета 1000 вместо предела 1000.Ваше условие WHERE ограничит количество отношений примерно 10% от всех возможных комбинаций Персона и Хобби.Здесь 500x20 = 1000, поэтому будет приблизительно 1000 отношений.

ПРИМЕЧАНИЕ. Использование лимита 1000 создаст отношения только с первыми двумя хобби.

Только для лимита 500будет использовано одно хобби, для лимита 1000 первых двух, для лимита 1500 первых 3 и т. д. (500 - это количество человек).

...