2016-04-27 6 views
2

Je suis dans ce mur en ce qui concerne les relations bidirectionnelles. Dites que j'essaie de créer un graphique qui représente un arbre généalogique. Le problème ici est que:
* Timmy peut être le frère de Suzie, mais
* Suzie ne peut pas être le frère de Timmy.Comment atténuer les relations bidirectionnelles dans un arbre généalogique, dans Neo4j?

Ainsi, il devient nécessaire de modéliser ce dans 2 directions:

enter image description here

(Bien sûr, techniquement je pourrais dire SIBLING_TO et ne laisser qu'un seul bord ... ce que je ne suis pas sûr de ce que le vocabulaire C'est quand j'essaie de connecter une grand-mère à un petit-fils.)

Quand tout est dit et fait, je suis sûr qu'il n'y a aucun moyen de contourner le fait que la direction importe dans cet exemple.

Je lisais ce blog post, en ce qui concerne les erreurs courantes de Neo4j. L'auteur affirme que cette bidirectionnalité n'est pas le moyen le plus efficace de modéliser des données dans Neo4j et devrait être évitée.

Et je commence à être d'accord. J'ai mis en place un jeu simulé de 2 familles:
enter image description here et j'ai trouvé que beaucoup de requêtes que j'essayais de lancer allaient très, très lentement. C'est en raison de la nature «tout connecté à tous» du graphique, au moins dans chaque famille respective.

Ma question est la suivante:
1) Ai-je raison de dire que la bidirectionnalité n'est pas idéale? 2) Si oui, mon exemple d'arbre généalogique est-il représentable d'une autre manière ... et quelle est la «meilleure pratique» dans les nombreuses situations où mon problème peut survenir?

3) S'il n'est pas possible de représenter l'arbre généalogique d'une autre manière, est-il techniquement possible d'écrire encore des requêtes de manière à contourner le problème de 1)?

Merci d'avoir lu ceci et de vos commentaires.

+0

liens bidirectionnels du même nom de bord sont redondants et sans valeur ajoutée . frère-à et soeur-à transmettre quelques informations, bien que cela pourrait être déduit d'une propriété. une relation (enfant) - [: PARENT] -> (parent) vous permet d'avoir la relation parent/enfant et d'obtenir toute la relation famille biologique, et vous pouvez l'utiliser pour chaque génération de parents/enfants. Step kids serait une question différente. –

Répondre

1

Le stockage d'informations redondantes (vos relations bidirectionnelles) dans une base de données n'est jamais une bonne idée. Voici une meilleure façon de représenter un arbre généalogique.

Pour indiquer "siblingness", vous n'avez besoin que d'un seul type de relation, par exemple SIBLING_OF, et vous n'avez besoin que d'une seule relation de ce type entre deux nœuds frères. Pour indiquer l'ascendance, vous n'avez besoin que d'un type de relation unique, disons CHILD_OF, et vous n'avez besoin que d'une seule relation de ce type entre un enfant et chacun de ses parents.

Vous devez également avoir une étiquette de noeud pour chaque personne, par exemple Person. Et chaque personne doit avoir une propriété d'ID unique (disons, id), et une sorte de propriété indiquant le genre (par exemple, un booléen isMale).

Avec ce modèle de données très simple, voici quelques exemples de requêtes:

  1. Pour trouver les sœurs de la personne 123 (notez que le modèle ne spécifie pas de sens de la relation):

    MATCH (p:Person {id: 123})-[:SIBLING_OF]-(sister:Person {isMale: false}) 
    RETURN sister; 
    
  2. Pour trouver les grands-pères de Person 123 (notez que ce modèle spécifie que les chemins correspondants doivent avoir une profondeur de 2):

    MATCH (p:Person {id: 123})-[:CHILD_OF*2..2]->(gf:Person {isMale: true}) 
    RETURN gf; 
    
  3. Pour trouver personne 123 grands-petits-enfants:

    MATCH (p:Person {id: 123})<-[:CHILD_OF*3..3]-(ggc:Person) 
    RETURN ggc; 
    
  4. Pour trouver des oncles maternels de la personne 123:

    MATCH (p:Person {id: 123})-[:CHILD_OF]->(:Person {isMale: false})-[:SIBLING_OF]-(maternalUncle:Person {isMale: true}) 
    RETURN maternalUncle; 
    
+0

Cette réponse était exactement ce que j'avais besoin d'entendre - merci beaucoup. Bien que l'idée derrière la directionnalité soit toujours vague dans ma tête (pourquoi appliquer la direction si elle peut ou non être non pertinente?), L'idée de réduire la redondance afin que vous ayez le nombre minimum de relations est absolument dorée. Les exemples de requêtes sont fantastiques. Merci encore. –

0

Je ne suis pas sûr si vous êtes conscient qu'il est possible d'interroger de manière bidirectionnelle (c'est-à-dire d'ignorer la direction). Donc, vous pouvez faire:

MATCH (a)-[:SIBLING_OF]-(b) 

et puisque je ne suis pas correspondre à une direction, il va aller dans les deux sens. Voilà comment je suggérerais de modéliser les choses.

En règle générale, vous ne souhaitez créer des relations multiples que si vous souhaitez stocker différents états. Par exemple, une relation KNOWS ne peut s'appliquer que d'une manière car la personne A peut connaître la personne B, mais B peut ne pas connaître A. De même, vous pouvez avoir une relation LIKES avec une propriété value indiquant A comme B et des forces différentes de "aimer" dans les deux directions

+0

Seriez-vous d'accord que «petite-fille de» et «grand-mère de» sont des états différents, et donc nécessitent des relations multiples? –

+0

Je ne pense pas ... Je dirais que ces deux relations sont différentes façons de représenter le même état de fait dans votre base de données. C'est un aspect de la modélisation dans Neo4j. Vous devez en choisir un et rester avec lui –

+0

Mieux encore, cependant, si cela a du sens pour vous, est de trouver des grands-parents en faisant correspondre un chemin de deux child_of relations. Mais vous n'avez pas toujours cela et vous voulez toujours représenter la relation de petit-enfant –