Recorriendo nodos en Neo4j y creando relaciones
-
20-12-2019 - |
Pregunta
Esta es una extensión de otro SO (¿Neo4j 2.0 se fusiona con un error de rendimiento de restricciones únicas?), pero lo estoy intentando de otra manera.
MATCH (c:Contact),(a:Address), (ca:ContactAddress)
WITH c,a,collect(ca) as matrix
FOREACH (car in matrix |
MERGE
(c {ContactId:car.ContactId})
-[r:CONTACT_ADDRESS {ContactId:car.ContactId,AddressId:car.AddressId}]->
(a {AddressId:car.AddressId}))
Entonces esto lleva a un servidor Neo4j bloqueado.Estoy tratando de entender por qué.
Mi proceso de pensamiento detrás de la consulta es el siguiente:
- Quiero seleccionar todos los nodos de Contacto y Dirección (así como los nodos de Dirección de Contacto)
- Quiero recorrer todos los nodos ContactAddress (que contienen los datos de relación entre Contacto y Dirección) y relacionar los nodos Contacto y Dirección entre sí.
Cuando ejecuto el código anterior, el servidor tiene aproximadamente un 40% de CPU y la memoria continúa aumentando.Lo detuve después de que el navegador se conectó y se desconectó (myserver:7474/browser), reinicié mi base de datos y lo intenté nuevamente, esta vez usando lo siguiente:
match (c:Contact),(a:Address), (ca:ContactAddress)
WITH c,a,collect(distinct ca) as matrix
foreach (car in matrix |
CREATE
(c {ContactId:car.ContactId})
-[r:CONTACT_ADDRESS {ContactId:car.ContactId,AddressId:car.AddressId}]->
(a {AddressId:car.AddressId}))
Mismos resultados.Base de datos Neo4j bloqueada y desconectada mientras la CPU permanece fija y el uso de RAM continúa aumentando.¿Hay algún bucle aquí que no veo?
También probé esto (con el mismo problema):
FOREACH(row in {PassedInList} |
MERGE (c:Contact {ContactId:row.ContactId})
MERGE (a:Address {AddressId:row.AddressId})
MERGE (c)-[r:CONTACT_ADDRESS]->(a)
)
RESUELTO:
MATCH (ca:ContactAddress)
MATCH (c:Contact {ContactId:ca.ContactId}), (a:Address {AddressId:ca.AddressId})
MERGE p = (c)
-[r:CONTACT_ADDRESS {ContactId:ca.ContactId,AddressId:ca.AddressId}]->
(a)
Solución
Cuando escribes match (c:Contact),(a:Address), (ca:ContactAddress)
, con 3 nodos desconectados, Neo4j coincidirá con todos los productos cartesianos posibles de esos 3.Si tuviera 100 de cada tipo de nodo, eso sería 100x100x100 = 1000000 resultados.
Prueba esto:
MATCH (ca:ContactAddress), (c:Contact {ContactId:ca.ContactId}), (a:Address {AddressId:ca.AddressId})
MERGE (c)-[r:CONTACT_ADDRESS {ContactId:ca.ContactId,AddressId:ca.AddressId}]->(a)
Eso coincidirá con cada :ContactAddress
nodo, y sólo el :Contact
y :Address
nodos que coincidan con él.Luego creará la relación (si aún no existía).
Si quieres ser más claro, también puedes dividir el MATCH
, es decir:
MATCH (ca:ContactAddress)
MATCH (c:Contact {ContactId:ca.ContactId}), (a:Address {AddressId:ca.AddressId})
MERGE (c)-[r:CONTACT_ADDRESS {ContactId:ca.ContactId,AddressId:ca.AddressId}]->(a)