refcard - neo4j tutorial
Nodo de retorno si la relación no está presente (6)
Escribí una idea general que muestra cómo se puede hacer esto de forma natural utilizando Cypher 2.0
http://gist.neo4j.org/?9171581
El punto clave es usar la coincidencia opcional con los ingredientes disponibles y luego comparar para filtrar los ingredientes faltantes (nulos) o los ingredientes con el valor incorrecto.
Tenga en cuenta que la noción es declarativa y no necesita describir un algoritmo, simplemente escriba lo que necesita.
Estoy tratando de crear una consulta usando una clave que "Buscará" los ingredientes faltantes que podría tener un chef. Mi gráfico está configurado de esta manera:
(ingredient_value)-[:is_part_of]->(ingredient)
(ingredient)
tendría una clave / valor de nombre = "colores de tinte". (ingredient_value)
podría tener una clave / valor de valor = "rojo" y "es parte de" el (ingredient, name="dye colors")
.
(chef)-[:has_value]->(ingredient_value)<-[:requires_value]-(recipe)-[:requires_ingredient]->(ingredient)
Estoy utilizando esta consulta para obtener todos los ingredients
, pero no sus valores reales, que requiere una receta, pero me gustaría que solo se devuelvan los ingredients
que el chef no tiene, en lugar de todos los ingredientes que requiere cada receta. Lo intenté
(chef)-[:has_value]->(ingredient_value)<-[:requires_value]-(recipe)-[:requires_ingredient]->(ingredient)<-[:has_ingredient*0..0]-chef
pero esto no devolvió nada.
¿Es esto algo que puede lograrse con cypher / neo4j o es algo que se maneja mejor devolviendo todos los ingredientes y ordenándolos yo mismo?
Bonus: También hay una forma de usar la clave para hacer coincidir todos los valores que tiene un chef con todos los valores que requiere una receta. Hasta ahora solo he devuelto todas las coincidencias parciales que son devueltas por un chef-[:has_value]->ingredient_value<-[:requires_value]-recipe
y agregando los resultados yo mismo.
He completado esta tarea utilizando gremlin. yo si
x=[]
g.idx(''Chef'')[[name:''chef1'']].as(''chef'')
.out(''has_ingredient'').as(''alreadyHas'').aggregate(x).back(''chef'')
.out(''has_value'').as(''values'')
.in(''requires_value'').as(''recipes'')
.out(''requires_ingredient'').as(''ingredients'').except(x).path()
Esto devolvió los caminos de todos los ingredientes faltantes. No pude formular esto en el lenguaje de cifrado, al menos para la versión 1.7.
La última consulta debe ser:
START chef = node(..)
MATCH (chef)-[:has_value]->(ingredient_value)<-[:requires_value]-(recipe)-[:requires_ingredient]->(ingredient)
WHERE (ingredient)<-[:has_ingredient]-chef
RETURN ingredient
Este patrón: (ingredient)<-[:has_ingredient*0..0]-chef
Es la razón por la que no devolvió nada. *0..0
significa que la longitud de las relaciones debe ser cero, lo que significa que el ingrediente y el chef deben ser el mismo nodo, y no lo son.
Para recuperar nodos sin ninguna relación.
Esta es la buena opción para comprobar si la relación existe o no.
MATCH (player)-[r:played]->()
WHERE r IS NULL
RETURN player
También puede verificar múltiples condiciones para esto. Devolverá todos los nodos, los cuales no han "jugado" o "no jugó" la relación.
MATCH (player)
WHERE NOT (player)-[:played|notPlayed]->()
RETURN player
Para buscar nodos que no tengan ninguna relación.
MATCH (player)
WHERE NOT (player)-[r]-()
RETURN player
Verificará el nodo que no tenga ninguna relación entrante / saliente.
Si necesita "exclusión condicional" semántica, puede lograrlo de esta manera.
A partir de neo4j 2.2.1, puede usar la cláusula OPTIONAL MATCH
y filtrar los nodos no NULL
( NULL
).
También es importante utilizar la cláusula WITH
entre las cláusulas OPTIONAL MATCH
y WHERE
, de modo que la primera WHERE
define una condición para la coincidencia opcional y la segunda WHERE
comporte como un filtro.
Suponiendo que tenemos 2 tipos de nodos: Person
y Communication
. Si quisiera obtener todas las Personas que nunca se comunicaron por teléfono, pero que se comunicaron de otra manera, haría esta consulta:
MATCH (p: Person)
OPTIONAL MATCH p--(c: Communication)
WHERE c.way = ''telephone''
WITH p, c
WHERE c IS NULL
RETURN p
El patrón de coincidencia coincidirá con todas las Personas con sus comunicaciones, donde c
será NULL
para las comunicaciones no telefónicas. Luego, el filtro ( WHERE
WITH
) filtrará las comunicaciones telefónicas dejando todos los demás.
Referencias:
http://neo4j.com/docs/stable/query-optional-match.html#_introduction_3 http://java.dzone.com/articles/new-neo4j-optional
Actualización 01/10/2013:
Encontré esto en la referencia Neo4j 2.0 :
Trate de no usar relaciones opcionales. Sobre todo,
No los uses así:
MATCH a-[r?:LOVES]->() WHERE r IS NULL
donde solo asegúrate de que no existan.
En su lugar haz esto así:
MATCH a WHERE NOT (a)-[:LOVES]->()
Usando cypher para verificar si la relación no existe:
...
MATCH source-[r?:someType]-target
WHERE r is null
RETURN source
Los ? marca hace la relación opcional.
O
En neo4j 2 hacer:
...
OPTIONAL MATCH source-[r:someType]-target
WHERE r is null
RETURN source
Ahora puede verificar la relación no existente (nula).