Neo4J Cypher中的嵌套FOREACH运行无限

Neo4J Cypher中的嵌套FOREACH运行无限,neo4j,cypher,Neo4j,Cypher,我尝试运行以下查询,其中我在数据库中有10个链,在10个国家/地区有10个链。使用20个地址的数组。 然后我循环这些,为每个国家、连锁店和地址组合创建一个商店,期望10*10*20个组合-2000个商店。 但相反,查询会一直运行,直到创建了大约200000条记录,然后由于未知错误而停止 MATCH (Chains:Chain), (Countries:Country) WITH Collect(Chains) as ch, Collect(Countries) as cou, ['

我尝试运行以下查询,其中我在数据库中有10个链,在10个国家/地区有10个链。使用20个地址的数组。 然后我循环这些,为每个国家、连锁店和地址组合创建一个商店,期望10*10*20个组合-2000个商店。 但相反,查询会一直运行,直到创建了大约200000条记录,然后由于未知错误而停止

MATCH (Chains:Chain), (Countries:Country)
WITH Collect(Chains) as ch, 
     Collect(Countries) as cou, 
['Ullevål','Blindern','Centrum','Kringså','Lysaker','Skøyen','Fornebu','Stortinget','Nationalteatre','KarlJohan',
'Gamle','Grunerløkka','Grønland','Majorstuen','Snarøya','Asker','Sandvika','Drammen','Gothenburg','Stockholm'] as addresses

FOREACH(country in cou |
    FOREACH (c in ch |
            FOREACH (a in addresses |
                CREATE (s:Store {name:c.name+"_"+a, address:a})
                CREATE (s-[:BELONGS_TO]->c)
                CREATE (s-[:IN]->country)               )))

如果您有以下数据

FOREACH (i IN RANGE(1, 10) | 
    CREATE (:Chain {name:'Chain' + i}), 
           (:Country {name:'Country' + i})
)
…您查询的第一部分

MATCH (Chains:Chain), (Countries:Country)
WITH COLLECT(Chains) AS ch, COLLECT(Countries) AS cou
将导致
ch
cou
的长度为100的集合,因为
MATCH
正在检索笛卡尔积(10^2=100)。这就是你200000张唱片的来源:100*100*20。您可以通过以下方式验证这一点:

MATCH (Chains:Chain), (Countries:Country)
WITH COLLECT(Chains) AS ch, COLLECT(Countries) AS cou
RETURN LENGTH(ch), LENGTH(cou)
这将告诉您每个集合的长度为100:

LENGTH(ch)  LENGTH(cou)
100         100
您可以通过在查询的第一部分中使用
COLLECT(DISTINCT thing)
来修复此问题,以便仅收集唯一的内容

MATCH (Chains:Chain), (Countries:Country)
WITH COLLECT(DISTINCT Chains) AS ch, COLLECT(DISTINCT Countries) AS cou
RETURN LENGTH(ch), LENGTH(cou)
…这将告诉您
ch
cou
是长度为10的集合:

LENGTH(ch)  LENGTH(cou)
10          10
现在,嵌套的
FOREACH
将创建10*10*20=2000条记录:

MATCH (Chains:Chain), (Countries:Country)
WITH Collect(DISTINCT Chains) as ch, 
     Collect(DISTINCT Countries) as cou, 
     ['Ullevål','Blindern','Centrum','Kringså','Lysaker','Skøyen','Fornebu','Stortinget','Nationalteatre','KarlJohan',
      'Gamle','Grunerløkka','Grønland','Majorstuen','Snarøya','Asker','Sandvika','Drammen','Gothenburg','Stockholm'] as addresses

FOREACH(country in cou |
    FOREACH (c in ch |
        FOREACH (a in addresses |
            CREATE (s:Store {name:c.name+"_"+a, address:a})
            CREATE (s-[:BELONGS_TO]->c)
            CREATE (s-[:IN]->country)               )))

“添加2000个标签,创建2000个节点,设置4000个属性,创建4000个关系,在1262毫秒内返回0行。”

如果您有以下数据

FOREACH (i IN RANGE(1, 10) | 
    CREATE (:Chain {name:'Chain' + i}), 
           (:Country {name:'Country' + i})
)
…您查询的第一部分

MATCH (Chains:Chain), (Countries:Country)
WITH COLLECT(Chains) AS ch, COLLECT(Countries) AS cou
将导致
ch
cou
的长度为100的集合,因为
MATCH
正在检索笛卡尔积(10^2=100)。这就是你200000张唱片的来源:100*100*20。您可以通过以下方式验证这一点:

MATCH (Chains:Chain), (Countries:Country)
WITH COLLECT(Chains) AS ch, COLLECT(Countries) AS cou
RETURN LENGTH(ch), LENGTH(cou)
这将告诉您每个集合的长度为100:

LENGTH(ch)  LENGTH(cou)
100         100
您可以通过在查询的第一部分中使用
COLLECT(DISTINCT thing)
来修复此问题,以便仅收集唯一的内容

MATCH (Chains:Chain), (Countries:Country)
WITH COLLECT(DISTINCT Chains) AS ch, COLLECT(DISTINCT Countries) AS cou
RETURN LENGTH(ch), LENGTH(cou)
…这将告诉您
ch
cou
是长度为10的集合:

LENGTH(ch)  LENGTH(cou)
10          10
现在,嵌套的
FOREACH
将创建10*10*20=2000条记录:

MATCH (Chains:Chain), (Countries:Country)
WITH Collect(DISTINCT Chains) as ch, 
     Collect(DISTINCT Countries) as cou, 
     ['Ullevål','Blindern','Centrum','Kringså','Lysaker','Skøyen','Fornebu','Stortinget','Nationalteatre','KarlJohan',
      'Gamle','Grunerløkka','Grønland','Majorstuen','Snarøya','Asker','Sandvika','Drammen','Gothenburg','Stockholm'] as addresses

FOREACH(country in cou |
    FOREACH (c in ch |
        FOREACH (a in addresses |
            CREATE (s:Store {name:c.name+"_"+a, address:a})
            CREATE (s-[:BELONGS_TO]->c)
            CREATE (s-[:IN]->country)               )))

“添加了2000个标签,创建了2000个节点,设置了4000个属性,创建了4000个关系,在1262毫秒内返回了0行。”

Brilliant!成功了。多谢各位。那么,您是说MATCH(Chains:Chain),(Countries:Country)而不是匹配单个节点,将尝试检索它们之间的所有对组合吗?X国家?这对我来说是出乎意料的me@DavletD对将其与SQL进行比较。如果从两个表中选择两列而不指定任何其他内容,则默认情况下将执行交叉联接(返回笛卡尔乘积)。例如,
从t1,t2中选择t1.thing,t2.otherthing
将为您提供笛卡尔乘积,因为您没有指定任何关于如何连接行的内容。类似地,在Cypher中,
MATCH(t1:Table1),(t2:Table2)返回t1.thing,t2。其他东西将返回笛卡尔乘积。对于这两种情况,您都需要指定
其中t1.id=t2.id
或类似的内容来减少结果集。谢谢@Nicole,这很有意义!成功了。多谢各位。那么,您是说MATCH(Chains:Chain),(Countries:Country)而不是匹配单个节点,将尝试检索它们之间的所有对组合吗?X国家?这对我来说是出乎意料的me@DavletD对将其与SQL进行比较。如果从两个表中选择两列而不指定任何其他内容,则默认情况下将执行交叉联接(返回笛卡尔乘积)。例如,
从t1,t2中选择t1.thing,t2.otherthing
将为您提供笛卡尔乘积,因为您没有指定任何关于如何连接行的内容。类似地,在Cypher中,
MATCH(t1:Table1),(t2:Table2)返回t1.thing,t2。其他东西将返回笛卡尔乘积。对于这两种情况,您都需要指定
其中t1.id=t2.id
或类似的内容来减少结果集。谢谢@Nicole,这现在是有意义的