在节点之间创建随机关系

时间:2018-08-17 14:47:08

标签: neo4j cypher

我有一个包含1,000个公司,1,000个人员和2,000个银行帐户的数据库。我想将每个公司的一个银行帐户与每个人的一个银行(没有银行帐户)与多个实体进行随机配对。

我尝试了以下操作但未成功:

MATCH (a:PERSON), (b:BANK_ACCOUNT)
WHERE NOT (a)-[:HAS_BANK_ACCOUNT]->(:BANK_ACCOUNT) 
AND NOT (b)<-[:HAS_BANK_ACCOUNT]-(:COMPANY|:PERSON)
MERGE (a)-[:HAS_BANK_ACCOUNT]->(b);

MATCH (COMPANY), (b:BANK_ACCOUNT)
WHERE NOT (a)-[:HAS_BANK_ACCOUNT]->(:BANK_ACCOUNT) 
AND NOT (b)<-[:HAS_BANK_ACCOUNT]-(:COMPANY|:PERSON)
MERGE (a)-[:HAS_BANK_ACCOUNT]->(b);

你能帮忙吗?

最好

2 个答案:

答案 0 :(得分:1)

如何使用APOC rock_n_roll

做这样的事情
// iterate over people 
// and create a relationship to one bank
// that does not already have the HAS_BANK_ACCOUNT
CALL apoc.periodic.rock_n_roll(
    'MATCH (a:PERSON)
     WHERE NOT (a)-[:HAS_BANK_ACCOUNT]->() 
     RETURN a AS a',
    'WITH {a} AS a MATCH (b:BANK_ACCOUNT)
     WHERE NOT (b)<-[:HAS_BANK_ACCOUNT]->() 
     WITH a, b
     LIMIT 1 
     MERGE (a)-[:HAS_BANK_ACCOUNT]->(b)',
    100
)

// repeat, but for companies this time
CALL apoc.periodic.rock_n_roll(
    'MATCH (a:COMPANY)
     WHERE NOT (a)-[:HAS_BANK_ACCOUNT]->() 
     RETURN a AS a',
    'WITH {a} AS a 
     MATCH (b:BANK_ACCOUNT)
     WHERE NOT (b)<-[:HAS_BANK_ACCOUNT]->() 
     WITH a, b
     LIMIT 1 
     MERGE (a)-[:HAS_BANK_ACCOUNT]->(b)',
    100
)

或者,只需稍作更改,您也可以一遍完成

CALL apoc.periodic.rock_n_roll(
    'MATCH (a)
     WHERE a:PERSON or a:COMPANY
     AND NOT (a)-[:HAS_BANK_ACCOUNT]->() 
     RETURN a AS a',
    'WITH {a} AS a 
     MATCH (b:BANK_ACCOUNT)
     WHERE NOT (b)<-[:HAS_BANK_ACCOUNT]->() 
     WITH a, b
     LIMIT 1 
     MERGE (a)-[:HAS_BANK_ACCOUNT]->(b)',
    100
)

如果您想使关系比添加关系的顺序更随机,则可以使用一行来随机化行驶MATCH语句。

CALL apoc.periodic.rock_n_roll(
    'MATCH (a)
     WHERE a:PERSON or a:COMPANY
     AND NOT (a)-[:HAS_BANK_ACCOUNT]->() 
     RETURN a AS a, rand() AS random
     ORDER BY random',
    'WITH {a} AS a 
     MATCH (b:BANK_ACCOUNT)
     WHERE NOT (b)<-[:HAS_BANK_ACCOUNT]->() 
     WITH a, b, rand() AS random
     ORDER BY random
     LIMIT 1 
     MERGE (a)-[:HAS_BANK_ACCOUNT]->(b)',
    100
)

答案 1 :(得分:1)

节点太少,您应该可以使用APOC收集功能进行混洗和压缩来轻松地做到这一点:

MATCH (b:BANK_ACCOUNT)
WITH collect(b) as accounts
WITH apoc.coll.shuffle(accounts) as accounts

MATCH (p:PERSON)
WITH accounts, collect(p) as persons
UNWIND apoc.coll.zip(persons, accounts[..1000]) as personAccount
WITH accounts, personAccount[0] as person, personAccount[1] as account
CREATE (person)-[:HAS_BANK_ACCOUNT]->(account)

WITH distinct accounts[1000..] as accounts

MATCH (c:COMPANY)
WITH accounts, collect(c) as companies
UNWIND apoc.coll.zip(companies, accounts) as companyAccount
WITH companyAccount[0] as company, companyAccount[1] as account
CREATE (company)-[:HAS_BANK_ACCOUNT]->(account)