# Neo4j

Neo4j è un software per basi di dati a grafo open source sviluppato interamente in Java. È un database totalmente transazionale, che viene integrato nelle applicazioni permettendone il funzionamento stand alone e memorizza tutti i dati in una cartella. È stato sviluppato dalla Neo Technology, una startup di Malmö, Svezia e della San Francisco Bay Area.

## Descrizione

Il database può essere usato sia in modalità embedded che server. Nella modalità embedded si incorpora il database nell'applicazione (con maven o includendo i file JAR) e questo viene eseguito all'interno della JVM, quindi nello stesso processo ma accettando vari thread concorrenti. Nella modalità server invece il database è un processo a sé stante a cui si accede tramite REST facendo delle query e ricevendo i dati in remoto; il server permette l'utilizzo di plugin che filtrano i dati in input e output e offrono servizi aggiuntivi, per esempio il supporto alle query spaziali. Neo4j permette la modalità batch, non concorrente, per l'importazione massiva di dati da altri database o da file, ma per l'uso comune si basa sulle transazioni. Una volta aperta una transazione è possibile creare nodi e assegnarvi delle proprietà, ossia dei valori corrispondenti ai tipi di dato elementari di Java (più le String e gli array) e identificati grazie a un nome. Inoltre è possibile unire dei nodi tramite le relazioni, i cui tipi sono definiti dal programmatore, che possono essere direzionali o meno. Anche le relazioni possono avere delle proprietà come i nodi. Il grafo è quindi schema-less, il che da un lato permette di definire dati molto eterogenei con il minimo sforzo e dall'altro può creare problemi di consistenza dei dati, che è interamente responsabilità dell'applicazione

### Indicizzazione

Neo4j integra un servizio di indicizzazione basato su Lucene che permette di memorizzare a piacere dei nodi facendo riferimento a una etichetta assegnata arbitrariamente, per poi accedere all'iteratore dei nodi con una certa etichetta recante un certo valore. È possibile anche effettuare le ricerche fulltext, una funzione centrale di Lucene, e esistono dei plugin del server che permettono di indicizzare automaticamente i nodi. È disponibile infine un servizio di indicizzazione basato sui timestamp che permette di ottenere i nodi corrispondenti a una ora e una data comprese in un certo intervallo.

### Accesso e manipolazione al database

Anche se è possibile accedere direttamente ai nodi e alle relazioni usando le funzioni di Neo4j, spesso le applicazioni utilizzano i due linguaggi per le query supportati da Neo4j, ossia Gremlin e Cypher. Mentre la versione embedded è usata quasi esclusivamente da Java o da linguaggi che utilizzano la JVM come Scala o Groovy, la versione server è accessibile tramite REST da qualsiasi linguaggio, e esistono delle librerie specifiche per semplificarne l'utilizzo in Python, C# e altri linguaggi, ma la macchina su cui viene eseguito il server deve essere ovviamente dotata di una JVM.

### Sharding e replicazione

Neo4j non supporta lo sharding dei dati, quindi l'intero grafo deve essere memorizzato in una sola macchina. È possibile invece attivare più istanze di uno stesso database eseguite contemporaneamente su diverse macchine, realizzando un'architettura master-slave gestita tramite Zookeeper che garantisce la consistenza finale delle varie versioni e rende più veloce l'accesso in lettura grazie alla divisione del lavoro tra i nodi.

### Vantaggi

La struttura a grafo di Neo4j si mostra estremamente comoda ed efficiente nel trattare strutture come gli alberi estratte ad esempio da file XML, filesystem e reti, che ovviamente vengono rappresentate con naturalezza da un grafo poiché sono esse stesse dei grafi. L'esplorazione di queste strutture risulta in genere più veloce rispetto a un database a tabelle perché la ricerca di nodi in relazione con un certo nodo è un'operazione primitiva e non richiede più passaggi, in genere tre impliciti in un join di SQL, su tabelle diverse. Ogni nodo contiene l'indice delle relazioni entranti e uscenti da esso, quindi la velocità di attraversamento del grafo non risente delle dimensioni complessive ma solo della densità dei nodi attraversati. Esistono delle implementazioni già pronte per le operazioni più comuni sui grafi, come la ricerca del cammino minimo tra due nodi tramite l'algoritmo di Dijkstra, la ricerca di cicli e il calcolo del diametro della rete.

### Svantaggi

Neo4j risulta scomodo rispetto a un database a tabelle interrogabile tramite query SQL nelle ricerche complesse, per esempio basate su confronti matematici tra i campi delle tuple, e di conseguenza sulle modifiche di massa basate su tali ricerche. Non esistono infatti analoghi dell'UPDATE offerto dai sistemi SQL, che risulta pesante per quanto riguarda le modifiche massicce del grafo. Neo4j inoltre non offre funzioni per memorizzare dati binari come audio, video o grossi blocchi di testo, che devono essere salvati in un filesystem o in un altro database memorizzando nel grafo un riferimento. Anche se un database neo4j può contenere fino a 32 miliardi di nodi, l'impossibilità di effettuare lo sharding dei dati lo rende poco adatto per i lavori ETL su più cluster, per cui sono disponibili, anche se ancora in fase sperimentale, architetture basate su Hadoop come Giraph.