2011-12-12 2 views
9

Je voudrais représenter le en changeant la force des relations entre les nœuds dans un graphique Neo4j.Représentant (et incrémentant) la force de la relation dans Neo4j

Pour un graphique statique, cela se fait facilement en définissant une propriété « force » sur la relation:

A --knows--> B 
     | 
    strength 
     | 
     3 

Cependant, pour un graphique qui doit être mise à jour au fil du temps, il y a un problème, étant donné que incrémenter La valeur de la propriété ne peut pas être effectuée de manière atomique (via l'interface REST) ​​car une lecture avant écriture est requise. L'incrémentation (plutôt que la simple mise à jour) est nécessaire si le graphique est mis à jour en réponse à des données transmises en continu. Je devrais soit m'assurer qu'un seul client REST lit et écrit à la fois (synchronisation externe), soit m'en tenir uniquement à l'API intégrée pour pouvoir utiliser les transactions intégrées. Cela peut être réalisable mais semble maladroit.

Une autre solution pourrait consister à enregistrer plusieurs relations, sans propriétés, de sorte que la « force » est en fait le nombre de relations, à savoir

A knows B 
A knows B 
A knows B 

signifie un rapport de force 3.

  • Inconvénient: seules forces entières peuvent être enregistrées
  • Avantage: pas de lecture avant écriture est nécessaire
  • Inconvénient: (probablement) plus de stockage nécessaire
  • Inconvénient: (probablement) beaucoup plus lent pour extraire la valeur depuis plusieurs relations doivent être extraites et comptées

Quelqu'un at-il essayé cette approche, et est-il susceptible de rencontrer des problèmes de performance, en particulier lors de la lecture ?

Existe-t-il une meilleure façon de modéliser cela?

Répondre

5

Bonne idée. Pour réduire le stockage et les lectures multiples, ces relations peuvent être regroupées en une seule dans un travail par lots exécuté de manière transactionnelle. Chaque rel peut également porter une valeur de poids individuelle, dont la valeur agrégée est utilisée comme poids. Il ne doit pas nécessairement être basé sur des entiers et peut également être négatif pour représenter des décréments.

Vous pouvez également écrire une petite extension de serveur pour la mise à jour transactionnelle d'une valeur de pondération sur une relation unique. Probablement même sens pour l'API REST (en plus de l'opération « set de valeur unique » ont une opération de modification de valeur unique.

PUT http://localhost:7474/db/data/node/15/properties/mod/foo 

Le corps contient la valeur delta (1,5, -10). Une autre idée serait remplacer le mot-clé mode par l'opération réelle

PUT http://localhost:7474/db/data/node/15/properties/add/foo 
PUT http://localhost:7474/db/data/node/15/properties/or/foo 
PUT http://localhost:7474/db/data/node/15/properties/concat/foo 

Que signifierait "incrémenter" dans un cas non entier?

+0

Merci - plusieurs possibilités intéressantes là-bas! Après avoir vérifié le dictionnaire, je pense qu'il est correct de parler d'incréments non entiers (bien que vous deviez clairement spécifier le montant)! – DNA

1

Dépend un peu de ce que vous ciblez en lecture et en écriture. Quelle sera la taille du graphique total?

+0

À première vue, je dirais quelques dizaines de millions de nœuds. Le nombre de relations est moins certain, mais probablement un petit multiple du nombre de nœuds. Le graphique serait constamment mis à jour, ajoutant ou mettant à jour des dizaines ou quelques centaines d'entités par seconde. La charge de lecture serait probablement assez légère; la sélection d'un petit nombre de nœuds dans la localité d'un nœud spécifié, par exemple. – DNA

+0

mmh, si vous pouvez regrouper les mises à jour dans plus de transactions un-par-un, vous devriez être bien la performance sage. –

2

Hmm un peu d'une approche différente, mais vous pourriez envisager d'utiliser un système de mise en file d'attente. J'utilise aussi l'interface Neo4j REST et je cherche à stocker une force relationnelle en constante évolution. Le projet est dans Rails et utilise Resque. Chaque fois qu'une mise à jour de la base de données Neo4j est requise, elle est placée dans une file d'attente Resque à remplir par un worker. Je n'ai qu'un seul employé travaillant sur la file d'attente Neo4j Resque, donc il n'essaie jamais d'effectuer plus d'une mise à jour Neo4j à la fois. Cela a l'avantage supplémentaire de ne pas obliger l'utilisateur à attendre les mises à jour de neo4j lorsqu'il effectue une action qui déclenche une mise à jour. Cependant, ce n'est qu'une solution viable si vous n'avez pas besoin d'utiliser/afficher instantanément les mises à jour de Neo4j (bien que cela dépende de la vitesse de votre employé et de la taille de votre file d'attente, cela ne devrait prendre que quelques secondes).

Questions connexes