Pregunta

Tengo una consulta como esta:

MATCH left, right 
WHERE (ID(right) IN [1, 2, 3] AND ID(left) IN [4, 5, 6]) 
WITH left, right 
  LIMIT 1 
RETURN left, right 
UNION MATCH left, right 
WHERE (ID(right) IN [1, 2, 3] AND ID(left) IN [4, 5, 6]) 
WITH left, right 
  SKIP 4 LIMIT 1 
RETURN left, right 
UNION MATCH left, right 
WHERE (ID(right) IN [1, 2, 3] AND ID(left) IN [4, 5, 6]) 
WITH left, right 
  SKIP 8 LIMIT 1 
RETURN left, right
CREATE UNIQUE left-[rel:FRIEND]->right 
RETURN rel;

En general, solo estoy creando un conjunto de datos para poder usarlo más adelante en la instrucción CREATE UNIQUE.
Obviamente, eso no funciona: el analizador de consultas dice que solo puedo usar la cláusula RETURN una vez.Mi pregunta es: ¿cómo componer un conjunto de datos en este caso?Intenté asignar un alias y usarlo en CREATE UNIQUE; tampoco puedo hacerlo funcionar.¿Qué estoy haciendo mal?¿Es este escenario siquiera posible?

¿Fue útil?

Solución

Puede que no entienda lo que busca, pero esto es lo que se me ocurre cuando miro su consulta.

Para empezar, aquí hay una adaptación de su consulta que utiliza SKIP y LIMIT sin RETURN o UNION.

MATCH left, right
WHERE ID(left) IN [1,2,3] AND ID(right) IN [4,5,6]
WITH left, right 
    LIMIT 1
CREATE UNIQUE left-[rel:FRIEND]->right
WITH [rel] as rels  //If you want to return the relationship later you can put it in a collection and bring it WITH
MATCH left, right
WHERE ID(left) IN [1,2,3] AND ID(right) IN [4,5,6]
WITH left, right, rels 
    SKIP 4 LIMIT 1
CREATE UNIQUE left-[rel:FRIEND]->right
WITH rels + [rel] as rels
MATCH left, right
WHERE ID(left) IN [1,2,3] AND ID(right) IN [4,5,6]
WITH left, right, rels 
    SKIP 8 LIMIT 1
CREATE UNIQUE left-[rel:FRIEND]->right
WITH rels + [rel] as rels
RETURN LENGTH(rels), rels  // You can return the relationships here but SKIP/LIMIT does its job also if you don't return anything

Pero esta consulta es un poco descabellada.En realidad, son tres consultas, de las cuales dos se han incluido artificialmente como subconsultas de la primera.Coincide con los mismos nodos nuevamente en cada subconsulta, y realmente no se gana nada ejecutando las consultas de esta manera en lugar de por separado (en realidad es más lento, porque en cada subconsulta también coincide con los nodos que sabe que no usará) .

Entonces mi primera sugerencia es usar START en lugar de MATCH...WHERE al obtener nodos por id.Tal como está, la consulta vincula cada nodo de la base de datos como "izquierda", y luego cada nodo de la base de datos como "derecha", y luego filtra todos los nodos vinculados a "izquierda" que no cumplen con la condición en el WHERE cláusula, y luego lo mismo para "derecho".Dado que esta parte de la consulta se repite tres veces, todos los nodos de la base de datos están vinculados un total de seis veces.Eso es costoso para crear tres relaciones.Si utiliza START Puede vincular los nodos que desee de inmediato.Esto realmente no responde a su pregunta, pero será más rápido y la consulta será más limpia.Entonces, usa START para obtener nodos por su identificación interna.

START left = node(1,2,3), right = node(4,5,6)

Lo segundo en lo que pienso es en la diferencia entre nodos y 'rutas' o 'elementos de resultados' cuando comparas patrones.Cuando vinculas tres nodos en "izquierda" y otros tres nodos en "derecha", no tienes tres elementos de resultado, sino nueve.Para cada nodo enlazado en "izquierda" obtienes tres resultados, porque hay tres posibles "derechas" con los que combinarlo.Si quisieras relacionar cada "izquierda" con cada "derecha", genial.Pero creo que lo que buscas son los elementos de resultado. (1),(4), (2),(5), (3),(6), y aunque parece conveniente vincular los tres nodos "izquierdos" y los tres nodos "derechos" en una consulta con colecciones de ID de nodos, luego debe hacer todo ese filtrado para deshacerse de las 6 coincidencias no deseadas.La consulta se vuelve compleja y engorrosa y, en realidad, es más lenta que ejecutar las consultas por separado.Otra forma de decir esto es decir que (1)-[:FRIEND]->(4) es un patrón distinto, no conectado (relevantemente) a los otros patrones que está creando.Sería diferente si quisieras crear (1)-[:FRIEND]->(2)<-[:FRIEND]-(3), entonces querrás manejar esos tres nodos juntos.Tal vez simplemente estés explorando usos marginales del cifrado, pero pensé que debería señalarlo.Por cierto, usando SKIP y LIMIT de esta manera está un poco fuera de tono, en realidad no están destinados a la coincidencia de patrones y el filtrado.También es impredecible, a menos que también uses ORDER BY, ya que no hay garantía de que los resultados estén en un orden determinado.No sabes qué elemento de resultado se transmite.De todos modos, en este caso, creo que sería mejor vincular los nodos y crear la relación en tres consultas separadas.

START left = node(1), right = node(4)
CREATE UNIQUE left-[rel:FRIEND]->right
RETURN rel

START left = node(2), right = node(5)
CREATE UNIQUE left-[rel:FRIEND]->right
RETURN rel

START left = node(3), right = node(6)
CREATE UNIQUE left-[rel:FRIEND]->right
RETURN rel

Como ya sabes que quieres esos tres pares, y no, digamos, (1),(4),(1),(5),(1),(6) Tendría sentido consultar solo esos pares, y la forma más sencilla es realizar consultas por separado.

Pero en tercer lugar, dado que las tres consultas son estructuralmente idénticas y solo difieren en el valor de la propiedad (si la identificación se considera una propiedad), puede simplificar la consulta generalizando o anonimizando lo que las distingue, es decirutilizar parámetros.

START left = node({leftId}), right = node({rightId})
CREATE UNIQUE left-[rel:FRIEND]->right
RETURN rel

parameters: {leftId:1, rightId:4}, {leftId:2, rightId:5}, {leftId:3, rightId:6}

Dado que la estructura es idéntica, Cypher puede almacenar en caché el plan de ejecución.Esto genera un buen rendimiento y la consulta es ordenada, fácil de mantener y se puede ampliar fácilmente si más adelante desea realizar la misma operación en otros pares de nodos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top