2011-09-24 13 views
18

Ho una domanda generale sulla modellazione in un database di diagrammi che non riesco proprio a spiegarmi.Come modellare le relazioni del mondo reale in un database grafico (come Neo4j)?

Come si modella questo tipo di relazione: "Newton ha inventato il calcolo"?

In un simple graph, si potrebbe modellare in questo modo:

Newton (node) -> invented (relationship) -> Calculus (node) 

... in modo che ci si dispone di un gruppo di "inventato" relazioni grafico come si è aggiunto più persone e invenzioni.

Il problema è, si inizia la necessità di aggiungere un po 'di proprietà al rapporto:

  • invention_date
  • influential_concepts
  • influential_people
  • books_inventor_wrote

... e vorrai iniziare a creare relazioni tra queste proprietà e altri nodi, come ad esempio:

  • influential_people: legame con la persona nodi
  • books_inventor_wrote: rapporto di prenotare nodi

Così ora sembra che le "relazioni del mondo reale" ("inventato") dovrebbe in realtà essere un nodo in il grafico, e il grafico dovrebbe essere simile a questo:

Newton (node) -> (relationship) -> Invention of Calculus (node) -> (relationship) -> Calculus (node) 

e a complicare le cose più, altre persone sono hanno partecipato anche nell'invenzione di calcolo, in modo da il grafico diventa ora qualcosa di simile:

Newton (node) -> 
    (relationship) -> 
    Newton's Calculus Invention (node) -> 
     (relationship) -> 
     Invention of Calculus (node) -> 
      (relationship) -> 
      Calculus (node) 
Leibniz (node) -> 
    (relationship) -> 
    Leibniz's Calculus Invention (node) -> 
     (relationship) -> 
     Invention of Calculus (node) -> 
      (relationship) -> 
      Calculus (node) 

chiedo Quindi la domanda perché sembra non si desidera impostare le proprietà del database grafico vero e proprio "rapporto" oggetti, perché può essere utile ad un certo punto trattarli come nodi nel grafico.

È corretto?

Ho studiato lo Freebase Metaweb Architecture e sembra che stiano trattando tutto come un nodo. Ad esempio, Freebase ha l'idea di un Mediator/CVT, in cui è possibile creare un nodo "Prestazioni" che collega un nodo "Attore" a un nodo "Film", come qui: http://www.freebase.com/edit/topic/en/the_last_samurai. Non sono sicuro se questo è lo stesso problema però.

Quali sono alcuni principi guida che si utilizzano per capire se la "relazione del mondo reale" dovrebbe effettivamente essere un nodo grafico anziché una relazione grafica?

Se ci sono buoni libri su questo argomento mi piacerebbe sapere. Grazie!

risposta

18

Alcune di queste cose, come invention_date, possono essere memorizzate come proprietà sui bordi come nella maggior parte dei database di grafici i bordi possono avere proprietà nello stesso modo in cui i vertici possono avere proprietà.Per esempio si potrebbe fare qualcosa di simile (codice segue TinkerPop's Blueprints):

Graph graph = new Neo4jGraph("/tmp/my_graph"); 
Vertex newton = graph.addVertex(null); 
newton.setProperty("given_name", "Isaac"); 
newton.setProperty("surname", "Newton"); 
newton.setProperty("birth_year", 1643); // use Gregorian dates... 
newton.setProperty("type", "PERSON"); 

Vertex calculus = graph.addVertex(null); 
calculus.setProperty("type", "KNOWLEDGE"); 

Edge newton_calculus = graph.addEdge(null, newton, calculus, "DISCOVERED"); 
newton_calculus.setProperty("year", 1666); 

Ora, consente di espandere un po 'e aggiungere in Leibniz:

Vertex liebniz = graph.addVertex(null); 
liebniz.setProperty("given_name", "Gottfried"); 
liebniz.setProperty("surnam", "Liebniz"); 
liebniz.setProperty("birth_year", "1646"); 
liebniz.setProperty("type", "PERSON"); 

Edge liebniz_calculus = graph.addEdge(null, liebniz, calculus, "DISCOVERED"); 
liebniz_calculus.setProperty("year", 1674); 

Aggiungendo nei libri:

Vertex principia = graph.addVertex(null); 
principia.setProperty("title", "Philosophiæ Naturalis Principia Mathematica"); 
principia.setProperty("year_first_published", 1687); 
Edge newton_principia = graph.addEdge(null, newton, principia, "AUTHOR"); 
Edge principia_calculus = graph.addEdge(null, principia, calculus, "SUBJECT"); 

Per scoprire tutti i libri che Newton ha scritto sulle cose, ha scoperto che possiamo costruire un attraversamento di grafici. Iniziamo con Newton, seguiamo i link da lui a cose che ha scoperto, poi attraversiamo i collegamenti al contrario per ottenere libri su quell'argomento e di nuovo andiamo indietro su un link per ottenere l'autore. Se l'autore è Newton, torna al libro e restituisci il risultato. Questa query è scritto in Gremlin, un linguaggio basato Groovy dominio specifico per attraversamenti grafico:

newton.out("DISCOVERED").in("SUBJECT").as("book").in("AUTHOR").filter{it == newton}.back("book").title.unique() 

Così, spero ho mostrato un po 'come un attraversamento intelligente può essere utilizzato per evitare problemi con la creazione di nodi intermedi per rappresentare bordi. In un piccolo database non importa molto, ma in un database di grandi dimensioni subirai grandi successi in termini di prestazioni.

Sì, è triste che non è possibile associare i bordi con altri spigoli in un grafico, ma questa è una limitazione delle strutture dati di questi database. A volte ha senso rendere tutto un nodo, ad esempio, in Mediator/CVT una performance ha anche un po 'più di concretezza. Gli individui possono desiderare di affrontare solo la performance di Tom Cruise in "The Last Samurai" in una recensione. Tuttavia, per la maggior parte dei database di grafici ho trovato che l'applicazione di alcuni traversamenti grafici può farmi ottenere ciò che voglio dal database.

+0

risposta eccellente! questo chiarisce davvero le cose per me, grazie. –

Problemi correlati