2011-12-12 13 views
9

Vorrei rappresentare lo cambiando la forza delle relazioni tra i nodi in un grafico Neo4j.Rappresenta (e incrementa) la forza della relazione in Neo4j

Per un grafico statico, questo è fatto facilmente impostando una proprietà "forza" sul rapporto:

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

Tuttavia, per un grafico che necessita di un aggiornamento nel corso del tempo, c'è un problema, dal momento che incrementazione il valore della proprietà non può essere eseguito atomicamente (tramite l'interfaccia REST) ​​poiché è richiesta una lettura-prima-scrittura. L'incremento (anziché il semplice aggiornamento) è necessario se il grafico viene aggiornato in risposta ai dati in ingresso in streaming.

Avrei bisogno di garantire che solo un client REST legga e scriva contemporaneamente (sincronizzazione esterna), o si attenga solo all'API incorporata in modo da poter utilizzare le transazioni integrate. Questo può essere praticabile ma sembra imbarazzante.

Un'altra soluzione potrebbe essere quella di registrare più rapporti, senza alcuna proprietà, in modo che la "forza" è in realtà il conteggio delle relazioni, cioè

A knows B 
A knows B 
A knows B 

significa un rapporto di forza 3.

  • Svantaggio: solo i punti di forza interi può essere registrato
  • Vantaggio: nessuna lettura prima della scrittura è richiesto
  • Svantaggio: (probabilmente) più spazio di archiviazione richiesto
  • Svantaggio: (probabilmente) molto più lento per estrarre il valore in quanto molteplici relazioni devono essere estratti e contati

Qualcuno ha provato questo approccio, ed è probabile imbattersi in problemi di prestazioni, soprattutto durante la lettura ?

C'è un modo migliore per modellarlo?

risposta

5

Bella idea. Per ridurre lo storage e le multi-read, queste relazioni possono essere aggregate a una in un processo batch eseguito a livello transazionale.

Ogni rel può anche contenere un valore di peso individuale, il cui valore aggregato viene utilizzato come peso. Non deve essere basato su numeri interi e potrebbe anche essere negativo per rappresentare i decrementi.

È anche possibile scrivere una piccola estensione server per l'aggiornamento di un valore di ponderazione su una singola relazione transazionale. Probabilmente anche senso per l'API REST (come aggiunta al funzionamento "set singolo valore" hanno un modificare il funzionamento singolo valore.

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

Il corpo contiene il valore delta (1,5, -10). Un'altra idea sarebbe quella di sostituire la parola chiave modalità per l'effettivo funzionamento.

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 

cosa sarebbe "incremento" significa in un caso non intero?

+0

Grazie - diverse possibilità interessanti lì! Dopo aver controllato il dizionario, penso che sia OK parlare di "incrementi" non interi (anche se chiaramente dovresti specificare l'importo)! – DNA

1

Dipende un po 'dal carico di lettura e scrittura che si sta prendendo di mira. Quanto sarà grande il grafico totale?

+0

A una ipotesi approssimativa, direi alcune decine di milioni di nodi. Il numero di relazioni è meno certo, ma probabilmente un piccolo multiplo del numero di nodi. Il grafico sarebbe costantemente aggiornato, aggiungendo o aggiornando decine o poche centinaia di entità al secondo. Il carico di lettura sarebbe probabilmente abbastanza leggero; selezionare un piccolo numero di nodi nella località di un nodo specificato, ad esempio. – DNA

+0

mmh, se è possibile raggruppare gli aggiornamenti in transazioni più grandi di uno a uno, si consiglia di ottenere prestazioni ottimali. –

2

Hmm un po 'un approccio diverso, ma si potrebbe considerare l'utilizzo di un sistema di accodamento. Sto usando l'interfaccia Neo4j REST e sto cercando di immagazzinare una forza relazionale in costante cambiamento. Il progetto è in Rails e utilizza Resque. Ogni volta che viene richiesto un aggiornamento al database Neo4j, viene inserito in una coda Resque per essere completato da un worker. Ho solo un lavoratore che lavora sulla coda di Neo4j Resque, quindi non tenta mai di eseguire più di un aggiornamento di Neo4j contemporaneamente.

Questo ha l'ulteriore vantaggio di non rendere l'utente in attesa degli aggiornamenti neo4j quando eseguono un'azione che attiva un aggiornamento. Tuttavia, è solo una soluzione praticabile se non è necessario utilizzare/visualizzare gli aggiornamenti Neo4j all'istante (anche se a seconda della velocità del lavoratore e della dimensione della coda, dovrebbero essere necessari solo pochi secondi).

Problemi correlati