Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Cypher: sintassi e struttura

Introduzione al linguaggio Cypher: sintassi e struttura del principale strumento per l'interfacciamento con il database NoSQL Neo4j.
Introduzione al linguaggio Cypher: sintassi e struttura del principale strumento per l'interfacciamento con il database NoSQL Neo4j.
Link copiato negli appunti

Come abbiamo detto nell’introduzione, Neo4j supporta come linguaggio
dichiarativo ufficiale Cypher, creato dal team di
Neo4j allo scopo di interagire con il database in modo molto semplice e con
una curva di apprendimento il più possibile bassa per sviluppatori abituati
ad usare SQL.

Inoltre, utilizzando il
driver JDBC per Neo4j, è possibile sostituire il database in qualsiasi stack JVM che utilizzi
JDBC, oppure utilizzarlo con molti strumenti di reportistica.

Per prima cosa, per quanto riguarda etichette, proprietà e
relazioni, Cypher è case-sensitive: questo significa che è
necessario prestare attenzione alle maiuscole quando si scrivono le query.
Se si seguono le convenzioni che segnaleremo in seguito, dovremmo facilmente evitare errori.

In Cypher, un’istruzione si compone generalmente di tre parti, una di
interrogazione, opzionalmente uno o più comandi, e un’istruzione di ritorno
per indicare eventuali valori da restituire. Come vedremo in seguito, più
istruzioni possono essere concatenate e si possono usare valori
precedentemente letti dal database. Questo significa che si possono
scrivere query come la seguente, in cui abbiamo l’interrogazione,
la ricerca di alcuni nodi, a seguire la creazione di una nuova relazione
con un nuovo nodo e infine la restituzione dei nodi trovati e creati.

MATCH (u)-[i:ISCRITTO_A]->(:Corso {nome: 'Corso di Neo4j'})
WHERE i.scadenza < '2017'
CREATE (u)-[:LEGGE]->(l:Libro { titolo: 'Neo4j Cookbook' })
RETURN u,l

Andiamo nel dettaglio della query precedente. Con la prima riga abbiamo
cercato tutti i nodi che abbiamo collegato alla variabile u,
aventi una relazione di tipo ISCRITTO_A che abbiamo collegato alla
variabile i, con un qualsiasi nodo avente la proprietà nome uguale al valore “Corso di Neo4j”. In questa prima parte
della query vengono selezionate quelle porzioni di grafo che soddisfano il
pattern appena specificato (pattern matching). Con la seconda riga abbiamo
filtrato i risultati selezionando solo quelli in cui la proprietà scadenza è specificata ed
è minore di 2017, come in SQL. Nella terza riga, invece, abbiamo creato, per ogni risultato trovato, una relazione di tipo LEGGE
tra il nodo u e un nuovo nodo avente la proprietà titolo
uguale al testo “Neo4j Cookbook”. Infine, con
<code>RETURN</code> abbiamo indicato di restituire i nodi u e l. Alcune annotazioni:

  1. se la prima istruzione non trova alcun nodo, non ci sarà alcuna creazione e quindi nessuna riga restituita;
  2. per ogni risultato trovato verrà creato un nuovo nodo con etichetta Libro. Più avanti vedremo come che è possibile creare pattern
    assicurandosi che siano unici.

Il risultato della query è il seguente:

╒═════════════════════════╤════════════════════════╕
│u                        │l                       │
╞═════════════════════════╪════════════════════════╡
│{username: verdi@html.it}│{titolo: Neo4j Cookbook}│
├─────────────────────────┼────────────────────────┤
│{username: rossi@html.it}│{titolo: Neo4j Cookbook}│
└─────────────────────────┴────────────────────────┘

Vediamo appunto che abbiamo nella prima colonna (u) il nodo
trovato sul database, mentre nella seconda (l) il nodo creato.

I pattern

Abbiamo visto che per valorizzare alcune variabili che rappresentano ciò che stiamo cercando nel database, dobbiamo specificare una parte di grafo da creare (CREATE) o da far corrispondere (MATCH).

La sintassi usata da Cypher per rappresentare questi pattern è molto semplice. Vediamone alcuni esempi.

Nodi

Tutto ciò che è tra parentesi tonde è un nodo. Detto ciò, è possibile esprimere varie condizioni; ad esempio:

  • () fa match con qualsiasi nodo;
  • (:Libro) corrisponde a qualsiasi nodo con etichetta User. Per convenzione, le etichette hanno la sola iniziale maiuscola;
  • ({ titolo: 'Neo4j Cookbook' , pagine: 210 }) corrisponde a qualsiasi nodo avente le proprietà titolo e pagine entrambe con in valori indicati. Per convenzione generalmente le proprietà sono tutte in minuscolo;
  • il pattern che specifica sia l’etichetta sia le proprietà: (:Libro { titolo: 'Neo4j Cookbook' , pagine: 210 }) corrisponde ai nodi che rispettano tutte le condizioni: sia l’etichetta sia le proprietà valorizzate con i valori indicati;
  • per indicare che vogliamo collegare il valore di una variabile ad ogni nodo che corrisponde al pattern, dobbiamo specificare il nome della variabile subito dopo l’apertura della parentesi: (cookbook:Libro { titolo: 'Neo4j Cookbook' , pagine: 210 }). In questo caso abbiamo dato il nome cookbook ai nodi trovati. Le variabili sono comode successivamente per referenziare gli elementi corrispondenti, come abbiamo visto in precedenza nella clausola WHERE.

Relazioni

Tutto ciò che è tra parentesi quadrate è una relazione, o una catena di relazioni. Ad esempio:

  • -[]- fa match con qualsiasi relazione, e qualsiasi verso;
  • -[]-> fa match con qualsiasi relazione, e verso dal nodo specificato a sinistra a quello di destra. Ovviamente la sintassi <-[]- indica il verso opposto;
  • -[i:ISCRITTO_A] corrisponde a qualsiasi relazione di tipo ISCRITTO_A. Per convenzione le etichette hanno la sola iniziale maiuscola;
  • -[{ scadenza: '2017-11-01'}]-> corrisponde a qualsiasi relazione avente la proprietà scadenza con il valore indicato. Anche qui per convenzione le proprietà sono in minuscolo;
  • il pattern che specifica sia il tipo sia le proprietà corrisponde a relazioni che rispettano tutte le condizioni, come abbiamo visto per i nodi. Per esempio: [:ISCRITTO_A { scadenza: '2017-11-01'}];
  • per indicare che vogliamo collegare il valore di una variabile ad ogni relazione che corrisponde al pattern, anche qui dobbiamo specificare il nome della variabile subito dopo l’apertura della parentesi: -[i:ISCRITTO_A]->;
  • se vogliamo indicare che tra due nodi ci può essere una catena con al massimo 2 relazioni, possiamo usare la sintassi -[*1..2]->. Naturalmente, possiamo combinare il pattern con quelli usati in precedenza e scrivere pattern fatti così: -[:CONOSCE*2..]- per indicare che vogliamo catene di relazioni di tipo CONOSCE con almeno 2 relazioni.

Ti consigliamo anche