/ / Trouver les nœuds (n) avec: relations PROPRIÉTAIRE avec les nœuds (a), (b) et (c) et aucun autre nœud - neo4j, cypher

Recherchez les nœuds (n) avec: relations de propriétaire avec les nœuds (a), (b) et (c) et aucun autre nœud - neo4j, cypher

Ma base de données Neo4j 3.2 a des nœuds (n) qui peut avoir :OWNER relations avec d'autres nœuds. Je veux trouver tous les nœuds (n) avec :OWNER relations spécifiquement avec les nœuds (a), (b), et (c) et plus spécifiquement à aucun autre nœud.

J'aurais pensé que cela se ferait assez facilement avec

MATCH (n), (o)
WHERE (
(n)-[:OWNER]->(o) AND o.uuid IN $owner_ids
AND NOT ((n)-[:OWNER]->(o) AND NOT o.uuid IN $owner_ids)
RETURN (n)

Mais cela ne fonctionne pas. Cette requête renvoie incorrectement des nœuds (n) avec :OWNER relations avec (a), (b), (c), et (d). J'ai aussi essayé

MATCH (n), (o)
WHERE (n)-[:OWNER]->(o) AND o.uuid IN $owner_ids
WITH (n),(o)
WHERE NOT ((n)-[:OWNER]->(o) AND NOT o.uuid IN $owner_ids)
RETURN (n)

Ainsi que ce qui ressemble à un million d'autres permutations en vain. Toutes les suggestions sont grandement appréciées!

METTRE À JOUR

Ce qui précède est un scénario simplifié. Comme demandé dans un commentaire, un exemple plus proche de la réalité est:

MATCH (a)<-[:ANSWER]-(:Person {uuid: $person_id}), (o)
WHERE (exists((o)<-[:OWNER]-(:Owner)<-[:OWNER]-(:Form)-[:ANSWER]->(a)) AND o.uuid IN $owner_ids)
AND NOT (exists((o)<-[:OWNER]-(:Owner)<-[:OWNER]-(:Form)-[:ANSWER]->(a)) AND NOT o.uuid IN $owner_ids)
RETURN (a)

La réponse complète est

MATCH (o)<-[:OWNER]-(:Owner)<-[:OWNER]-(:Form)-[:ANSWER]->(a)<-[:ANSWER]-(:Person {uuid: $person_id})
WHERE o.uuid IN $owner_ids
WITH (a), count(o) as cnt
WHERE cnt = size(()<-[:OWNER]-(:Owner)<-[:OWNER]-(:Form)-[:ANSWER]->(a))
RETURN (a)

Réponses:

1 pour la réponse № 1

En supposant que vous ajoutiez des étiquettes à votre graphique (utilisons:Node pour l'instant, bien qu'il ne soit pas clair dans votre description si tous les nœuds doivent être identiques ou si certains doivent utiliser des étiquettes différentes), et que vous avez une contrainte unique sur: Node (uuid) pour une recherche rapide, cela devrait fonctionner:

MATCH (n:Node)-[:OWNER]->(o:Node)
WHERE o.uuid IN $owner_ids
WITH n, count(o) as cnt
WHERE cnt = size((n)-[:OWNER]->())
RETURN n

Votre requête avait un produit cartésien entre n et o (le produit croisé de tous les nœuds de votre graphique les uns avec les autres), qui ne fonctionnera pas bien. Vous devez spécifier la relation dans le MATCH, pas le WHERE.

Quant au reste de la requête, nous obtenons, pour chaque n, le nombre de o nœuds (ceux avec les identifiants en question), et en veillant à ce que le nombre de: relations PROPRIÉTAIRE pour chaque n est égal à ce nombre. Si elle est supérieure, il existe: des relations PROPRIÉTAIRE avec d'autres nœuds, donc celles-ci sont filtrées.

le size() la fonction que nous utilisons, car nous ne spécifions rien pour le nœud final, est efficace pour obtenir le nombre de relations.


0 pour la réponse № 2

Si votre exigence était d'avoir les trois: relations PROPRIÉTAIRES présentes (pas n'importe quel sous-ensemble d'entre elles), alors j'utiliserais cette requête:

  WITH ["a", "b", "c"] AS ids
MATCH (n:Node)-[:OWNER]->(o:Node)
WITH n,
COUNT(CASE WHEN o.uuid IN ids THEN 1 END) AS matches_found,
size(ids) AS matches_desired,
count(o)  AS total_relationships
WHERE matches_found = matches_desired
AND matches_found = total_relationships
RETURN n
ORDER BY n.uuid