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.
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.
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.
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
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.
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.