web-dev-qa-db-fra.com

Renvoie le noeud si la relation n'est pas présente

J'essaie de créer une requête en utilisant un chiffrement qui "trouvera" les ingrédients manquants qu'un chef pourrait avoir. Mon graphique est configuré de la manière suivante:

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

(ingredient) aurait une clé/valeur de nom = "couleurs de teinture". (ingredient_value) pourrait avoir une clé/valeur de valeur = "rouge" et "fait partie de" la (ingredient, name="dye colors").

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

J'utilise cette requête pour obtenir tous les ingredients, mais pas leurs valeurs réelles, requises par une recette, mais je voudrais renvoyer uniquement le ingredients que le chef n'a pas, de tous les ingrédients nécessaires à chaque recette. j'ai essayé

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

mais cela n'a rien rendu.

Est-ce quelque chose qui peut être accompli par Cypher/neo4j ou est-ce que c'est quelque chose qui est mieux géré en retournant tous les ingrédients et en les triant moi-même?

Bonus: existe-t-il également un moyen d'utiliser Cypher pour faire correspondre toutes les valeurs d'un chef à toutes les valeurs requises par une recette? Jusqu'à présent, je n'ai renvoyé que tous les résultats partiels renvoyés par un chef-[:has_value]->ingredient_value<-[:requires_value]-recipe et agréger les résultats moi-même.

77
Nicholas

Mise à jour 01/10/2013:

Venu à travers cela dans la référence Neo4j 2.:

Essayez de ne pas utiliser de relations optionnelles. Surtout,

ne les utilisez pas comme ceci:

MATCH a-[r?:LOVES]->() WHERE r IS NULL où vous vous assurez simplement qu’ils n’existent pas.

Au lieu de cela, procédez comme suit:

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

Utilisation de cypher pour vérifier si la relation n'existe pas:

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

Le ? La marque rend la relation facultative.

OR

Dans neo4j 2 faire:

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

Vous pouvez maintenant vérifier s'il existe une relation (nulle) non existante.

141
Gil Stal

Pour récupérer des nœuds sans relation

C'est la bonne option pour vérifier si la relation existe ou non

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

Vous pouvez également vérifier plusieurs conditions pour cela. Il renverra tous les nœuds, qui n'ont pas de relation "jouée" ou "non jouée".

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

Pour chercher des noeuds qui n'ont pas de statut réel

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

Il vérifiera que le noeud n’a aucune relation entrante/sortante.

14
Satish Shinde

Si vous avez besoin de la sémantique "exclusion conditionnelle", vous pouvez y parvenir de cette façon.

A partir de neo4j 2.2.1, vous pouvez utiliser OPTIONAL MATCH clause et filtrer les nœuds non appariés (NULL).

Il est également important d’utiliser WITH clause entre les OPTIONAL MATCH et WHERE, de sorte que la première WHERE définit une condition pour la correspondance facultative et que la seconde WHERE se comporte comme un filtre.

En supposant que nous ayons 2 types de nœuds: Person et Communication. Si je souhaite que toutes les personnes n'ayant jamais communiqué par téléphone, mais ayant pu communiquer par d'autres moyens, je pose la question suivante:

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

Le modèle de correspondance fera correspondre toutes les personnes avec leurs communications où c sera NULL pour les communications non téléphoniques. Ensuite, le filtre (WHERE après WITH) filtrera les communications téléphoniques en laissant toutes les autres.

Les références:

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

7

La dernière requête devrait être:

START chef = node(..)
MATCH (chef)-[:has_value]->(ingredient_value)<-[:requires_value]-(recipe)-[:requires_ingredient]->(ingredient)
WHERE (ingredient)<-[:has_ingredient]-chef
RETURN ingredient

Ce motif: (ingredient)<-[:has_ingredient*0..0]-chef

Est-ce la raison pour laquelle il n'a rien retourné. *0..0 signifie que la longueur des relations doit être zéro, ce qui signifie que l'ingrédient et le chef doivent être le même noeud, ce qu'ils ne sont pas.

2
Andres

J'ai complété cette tâche en utilisant gremlin. J'ai fait

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()

Cela a renvoyé les chemins de tous les ingrédients manquants. Je n'ai pas pu formuler cela dans le langage chiffré, du moins pour la version 1.7.

2
Nicholas