2012-06-08 12 views
52

Estoy intentando crear una consulta utilizando cifra que "encontrar" ingredientes faltantes que un chef podría tener, Mi gráfico está configurado de este modo:nodo de retorno si la relación no está presente

(ingredient_value)-[:is_part_of]->(ingredient) 

(ingredient) sería tener una clave/valor de name = "colorear colores". (ingredient_value) podría tener una clave/valor de value = "red" y "es parte de" (ingredient, name="dye colors").

(chef)-[:has_value]->(ingredient_value)<-[:requires_value]-(recipe)-[:requires_ingredient]->(ingredient) 

estoy usando esta consulta para obtener toda la ingredients, pero no sus valores reales, que requiere una receta, pero me gustaría que el retorno sólo el ingredients que el chef no tiene, en lugar de toda la ingredientes que cada receta requiere. Intenté

(chef)-[:has_value]->(ingredient_value)<-[:requires_value]-(recipe)-[:requires_ingredient]->(ingredient)<-[:has_ingredient*0..0]-chef 

pero esto no devolvió nada.

¿Esto es algo que se puede lograr mediante cypher/neo4j o es algo que se maneja mejor devolviendo todos los ingredientes y clasificándolos?

Bonificación: También hay una manera de utilizar el cifrado para que coincida con todos los valores que un chef tiene para todos los valores que requiere una receta. Hasta ahora solo he devuelto todas las coincidencias parciales devueltas por chef-[:has_value]->ingredient_value<-[:requires_value]-recipe y agregando los resultados yo mismo.

+0

Marque aquí para obtener información relevante para v3: http://stackoverflow.com/questions/25673223/finding-nodes-that-do-not-have-specific- relationship-cypher-neo4j – Maciej

Respuesta

106

Actualización 01/10/2013:

encontramos con este en la referencia Neo4j 2.0:

trate de no usar las relaciones opcionales. Por encima de todo,

no los usa como esto:

MATCH a-[r?:LOVES]->() WHERE r IS NULL donde sólo asegúrese de que no existen.

En lugar de hacer esto, así:

MATCH a WHERE NOT (a)-[:LOVES]->() 

El uso de cifrado para comprobar si la relación no existe:

... 
MATCH source-[r?:someType]-target 
WHERE r is null 
RETURN source 

El? marca hace la relación opcional.

O

En Neo4j 2 do:

... 
OPTIONAL MATCH source-[r:someType]-target 
WHERE r is null 
RETURN source 

ya se puede comprobar que no existe relación (nulo).

+3

En Neo4j 2.0, use OPTIONAL MATCH para que coincida con las relaciones opcionales, es decir, el primer ejemplo sería OPTIONAL MATCH (fuente) - [r: someType] - (target) RETURN fuente, r – boggle

+0

Estoy tratando de tener un nodo etiquetado en DONDE NO, no funciona. Me gusta: COINCIDE a DONDE NO (a) - [: AMA] -> (Extraño), en este 'Extraño' es una etiqueta de nodo. Estoy usando neo4j versión 2.1.2 –

+0

¿Podría cambiar esta respuesta para reflejar la actualización? – NumenorForLife

1

La última consulta que 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 devuelve nada. *0..0 significa que la duración de las relaciones debe ser cero, lo que significa que el ingrediente y el chef deben ser el mismo nodo, lo que no es así.

+0

Sí, pero no devuelve el ingrediente deseado. Devuelve lo que el chef ya tiene en común con la receta, quiero descubrir la diferencia. – Nicholas

2

Completé esta tarea usando gremlin. Lo hice

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ó las rutas de todos los ingredientes faltantes. No pude formular esto en el lenguaje de cifrado, al menos para la versión 1.7.

2

me escribió una esencia que muestra cómo se puede hacer esto de forma natural utilizando Cypher 2,0

http://gist.neo4j.org/?9171581

El punto clave es el uso de fósforo opcional a los ingredientes disponibles y luego comparar filtrar por faltar (null) ingredientes o ingredientes con el valor equivocado.

Tenga en cuenta que la noción es declarativa y no necesita describir un algoritmo, simplemente escriba lo que necesita.

10

Para ir a buscar nodos con no cualquier relación

Ésta es la buena opción para comprobar la relación es existir o no

MATCH (player)-[r:played]->() 
    WHERE r IS NULL 
    RETURN player 

También puede comprobar varias condiciones para este Se devolverá todos los nodos, los cuales no haber tenido una relación de "jugada" o "no jugada".

MATCH (player) 
WHERE NOT (player)-[:played|notPlayed]->() 
RETURN player 

a buscar nodos que no tengan cualquiera realtionship

MATCH (player) 
WHERE NOT (player)-[r]-() 
RETURN player 

Se comprobará nodo no tener cualquier relación de entrada/salida.

+2

'PARTIDO (jugador) DONDE NO (jugador) - [r] -() RETORNO el jugador da ** Error de variable r no definido **. ¿Cómo puedo definir r? –

5

Si necesita la semántica de "exclusión condicional", puede lograrlo de esta manera.

A partir de neo4j 2.2.1, puede utilizar la cláusula OPTIONAL MATCH y filtrar los nodos no coincidentes (NULL).

También es importante utilizar WITH cláusula entre las cláusulas OPTIONAL MATCH y WHERE, de modo que WHERE se comporta como un filtro, no como parte del patrón de partido.

Suponiendo que tenemos 2 tipos de nodos: Person y Communication.Si quiero conseguir todas las personas que nunca se han comunicado por el teléfono, pero puede haber comunicado otras maneras, me gustaría hacer esta consulta:

MATCH (p: Person) 
OPTIONAL MATCH p--(c: Communication) 
WHERE c.way = 'telephone' 
WITH p, c 
WHERE c IS NULL 
RETURN p 

Tenga en cuenta que la primera WHERE cláusula se comporta igual que una parte del partido.

Referencias:

http://neo4j.com/docs/stable/query-optional-match.html#_introduction_3 http://java.dzone.com/articles/new-neo4j-optional

Cuestiones relacionadas