2015-01-07 17 views
5

Ho una serie di dati per un albero genealogico in Neo4j e sto cercando di costruire una query Cypher che produce un insieme di dati JSON set simile al seguente:Creazione di Alberi con Neo4j

{Name: "Bob", 
     parents: [ 
      {Name: "Roger", 
      parents: [ 
       Name: "Robert", 
       Name: "Jessica" 
      ]}, 
      {Name: "Susan", 
      parents: [ 
       Name: "George", 
       Name: "Susan" 
      ]} 
     ]} 

mio grafico ha una relazione di PARENT tra i nodi MEMBER (es. MATCH (p.Member) - [: PARENT] -> (c.Member)). Ho trovato Nested has_many relationships in cypher e neo4j cypher nested collect che finisce per raggruppare tutti i genitori insieme per il nodo figlio principale che sto cercando.

Aggiunta di una certa chiarezza sulla base del feedback:

Ogni membro ha un identificatore univoco. I sindacati sono attualmente tutti associati alla relazione PARENT. Tutto è indicizzato in modo che le prestazioni non ne risentano. Quando eseguo una query per ottenere di nuovo il grafico del nodo, ottengo i risultati che mi aspetto. Sto cercando di restituire un output che posso usare a scopo di visualizzazione con D3. Idealmente questo sarà fatto con una query di Cypher visto che sto usando l'API per accedere a neo4j dal frontend che si sta costruendo.

Aggiunta di una query di esempio:

MATCH (p:Person)-[:PARENT*1..5]->(c:Person) 
WHERE c.FirstName = 'Bob' 
RETURN p.FirstName, c.FirstName 

Questa query restituisce un elenco di ciascun genitore da cinque generazioni, ma invece di mostrare la gerarchia, è messa in vendita di 'Bob' come il bambino per ogni relazione. Esiste una query Cypher che mostri almeno ogni relazione nei dati? Posso formattare come devo da lì ...

+0

Maggiori informazioni si prega; stai usando l'API REST o un DB incorporato? Se utilizzi l'API REST, il tuo problema è semplificato forse dall'attività di trasformazione del JSON che l'API REST sputa, in questa struttura che stai cercando. http://neo4j.com/docs/stable/rest-api.html – FrobberOfBits

risposta

4

si potrebbe anche dare un'occhiata a Rik van Bruggens Blog on his family data:

Per quanto riguarda la query

È già creato un modello di percorso qui: (p:Person)-[:PARENT*1..5]->(c:Person) è possibile assegnare ad una variabile tree e poi operare su quella variabile, per esempio restituendo l'albero, o nodes(tree) o rels(tree) o operare su quella raccolta in altri modi:

MATCH tree = (p:Person)-[:PARENT*1..5]->(c:Person) 
WHERE c.FirstName = 'Bob' 
RETURN nodes(tree), rels(tree), tree, length(tree), 
     [n in nodes(tree) | n.FirstName] as names 

Vedi anche la scheda di riferimento cifra: http://neo4j.com/docs/stable/cypher-refcard e la formazione on-line http://neo4j.com/online-training per conoscere meglio Cypher.

Non dimenticare di

create index on :Person(FirstName); 
2

Suggerirei di creare un metodo per appiattire i dati in un array. Se gli oggetti non hanno UUID, probabilmente vorrai dargli degli ID mentre appiattisci e quindi avere una chiave parent_id per ogni record.

È quindi possibile eseguirlo come un set di query cifrate (effettuando più richieste all'API REST della query o utilizzando l'API REST batch) o in alternativa scaricare i dati in CSV e utilizzare il comando LOAD CSV di cypher per caricare gli oggetti.

Un comando cifra esempio con params sarebbe:

CREATE (:Member {uuid: {uuid}, name: {name}} 

E poi che attraversa la lista di nuovo con gli ID padre e figlio:

MATCH (m1:Member {uuid: {uuid1}}), (m2:Member {uuid: {uuid2}}) 
CREATE m1<-[:PARENT]-m2 

Assicurarsi di avere un indice sulla ID per i membri!

+0

Questo è vicino a quello che sto cercando. Non c'è modo di generare il set attraverso una singola query? Diciamo che voglio vedere l'albero per quattro o cinque generazioni da una determinata persona. Posso ottenere il grafico per mostrare i dati - Ho solo bisogno di un modo per trasformarlo tramite Cypher se possibile. In caso contrario, dovrò attenermi ai dati non elaborati che tornano dalla query di base e doverli elaborare nel formato che sto cercando. – OpenDataAlex

+0

Potrebbe essere possibile ottenerlo usando solo la cifratura, ma sospetto che non ne varrebbe la pena. –

+0

Oh, mi dispiace, ho letto male. Pensavo che volessi prendere JSON e trasformarlo in un database neo4j con cypher, ma tu vuoi il contrario –

2

I dati genealogici potrebbero essere conformi allo standard GEDCOM e includere due tipi di nodi: Persona e Unione. Il nodo Persona ha il suo identificatore e i soliti dati demografici. I nodi dell'Unione hanno un union_id e i fatti sul sindacato. In GEDCOM, la famiglia è un terzo elemento che riunisce questi due elementi. Ma in Neo4j, ho trovato opportuno includere anche union_id nei nodi Person. Ho usato 5 relazioni: padre, madre, marito, moglie e figlio. La famiglia è quindi composta da due genitori con un vettore interno e ogni bambino con un vettore esterno. L'immagine illustra questo. Questo è molto utile per visualizzare le connessioni e generare ipotesi. Per esempio, considera l'immagine allegata e il mio antenato Edward G Campbell, il prodotto dell'unione 1917 in cui tre fratelli sposarono tre sorelle Vaught dall'unione 8944 e due sorelle Gaither sposate dall'unione 2945. Inoltre, nell'angolo in alto a sinistra, come Mahala Campbell la sposò fratellastro John Greer Armstrong. Accanto a Mahala c'è Elizabeth Campbell, che è collegata per matrimonio ad altri Campbell, ma è probabilmente direttamente imparentata con loro. Allo stesso modo, puoi ipotizzare Rachael Jacobs in alto a destra e come potrebbe relazionarsi con gli altri Jacobs. Notice the query. From the few initial nodes visualized, you can click to open others. Uso inserzioni collettive che possono popolare ~ 30000 nodi Person e ~ 100.000 relazioni in poco più di un minuto.Ho una piccola funzione .NET che restituisce JSon da una visualizzazione dati; questa soluzione generica funziona con qualsiasi dataview in modo che sia scalabile. Sto ora lavorando per aggiungere altri dati, come ad esempio località (lat/long), documentazione (in particolare quella che collega persone, come un censimento), ecc.

0

L'unico modo che ho trovato finora per ottenere i dati sto cercando è quello di tornare in realtà le informazioni relazione, in questo modo:

MATCH ft = (person {firstName: 'Bob'})<-[:PARENT]-(p:Person) 
RETURN EXTRACT(n in nodes(ft) | {firstName: n.firstName}) as parentage 
ORDER BY length(ft); 

che restituirà un set di dati io sono quindi in grado di trasformarsi:

["Bob", "Roger"] 
["Bob", "Susan"] 
["Bob", "Roger", "Robert"] 
["Bob", "Susan", "George"] 
["Bob", "Roger", "Jessica"] 
["Bob", "Susan", "Susan"] 
+0

Ho scritto questa risposta mentre Michael stava scrivendo il suo :) Entrambi sono sulla stessa traccia quindi gli ho dato la risposta risolta. – OpenDataAlex

Problemi correlati