Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
vuoi
o PayPal
tutte le volte che vuoi
PERSONE SONO IN RELAZIONE DI AMICIZIA
3) (p1:Person {name: “Fabio”} ) – [:FRIEND OF] - - > (p2:Person {name:”Mario”} )
Esiste un nodo di tipo “person” che è l’etichetta, name è l’attributo del nodo, il valore è Fabio p1,
p2= identificativi hanno la funzione simile all’operatore di rinomina as in SQL, serve per dichiarare i
vari nodi e quando si richiamano è più semplice.
Struttura query in Cypher:
Una interrogazione Cypher si inizia sempre con MATCH pattern (proprietà che si sta cercando) RETURN
risultato (cosa si vuole ottenere)
MATCH (:Person {name: “Fabio”} )
– [:FRIEND OF] - > (friends)
RETURN friends
(Vantaggi dello schema free dei grafi in neo4j: se lo schema viene alterato e la query è scritta in un certo
modo, l’informazione tiene conto comunque dello schema modificato. Non solo la struttura si adatta in
automatico al dato, ma anche la query se scritta in maniera opportuna terrà conto del dato nuovo e della
struttura del dato. Se la query che ho scritto matcha comunque con la nuova struttura del dato, sarà
tenuto conto nella nuova query)
4) MATCH (:Person {name: “Fabio”} ) – [:FRIEND OF] - - > (friends) RETURN friends
5) COME CREARE I NODI E POTERLI MATCHARE in UNA RELAZIONE
create (:person :student {name: “Charlie”} )
create (:person :student {name: “Aurora”} )
match (a:person {name: “Charlie”}) , (b: person {name: “Aurora”})
create (a) – [:SAME_COURSE] - - > (b)
create (a:person {name: “Charlie”} )
create (:Skill {name: “Medicine”} )
match (a:Person), (b:skill)
where a.name = “Charlie” and b.name = “Medicine”
create (a) – [r:interested_in] - - > (b)
return r
6) COME CREARE SHORTESTPATH
Uno degli algoritmi famosissimi sui i grafi, rappresenta il percorso più breve per andare da un punto
A ad un punto B (un modo per connettere il dato con il percorso più breve)
create (:person :student {name: “Charlie”} )
create (:person :student {name: “Aurora”} )
create (:person :student {name: “Luca”} )
create (:person :student {name: “Eleonora”} )
match (a:person {name: “Charlie”}) , (b: person {name: “Aurora”}), (c:person {name: “Luca”} ) , (d:person
{name: “Eleonora”} )
create (a) – [:same_course] - - > (b)
create (b) – [:same_course] - - > (c)
create (c) – [:same_course] - - > (d) *
match p=shortestPath((n1:person {name:'Charlie'}) - [:same_course ] - (n2:person{name:'Eleonora'}))
return p
* = fai tutti i salti che vuoi, naviga tutte le relazioni che vuoi, basta che arrivi al risultato che ho chiesto
UN MODO PER CONNETTERE IL DATO IN MODO MOLTO VELOCE
7) ELIMINARE UN NODO
MATCH (n:work)
DETACH DELETE n
Constraints: più forte dell’indice
8) Indice:
Esercizio da sviluppare con neo4j:
Scaricare i file in formato CSV. Il graph DB permette di caricare il CSV, ci sono delle key-word per costruire il
grafo, per iniziare bisogna seguire questo script:
-creo le persone
LOAD CSV WITH HEADERS FROM 'file:/person.csv' AS row FIELDTERMINATOR ';'
CREATE (:person {name: row.name, gender: row.gender});
(meglio utilizzare non le virgolette “ “ ma gli apici ‘ ‘ )
-creo le skill
LOAD CSV WITH HEADERS FROM 'file:/skill.csv' AS row FIELDTERMINATOR ';'
CREATE (:skill {name: row.name});
-creo gli interessi delle persone (quindi le relazioni)
LOAD CSV WITH HEADERS FROM 'file:/interested_in.csv' AS row FIELDTERMINATOR ';'
MATCH (p:person {name:row.from}), (s:skill {name:row.to})
CREATE (p) – [r:INTERESTED_IN] -> (s);
(gli attributi si possono mettere anche con la WHERE piuttosto che con le parentesi graffe)
LOAD CSV WITH HEADERS FROM 'file:/interested_in.csv' AS row FIELDTERMINATOR ';'
MATCH (p:person), (s:skill) WHERE p.name = row.from AND s.name=row.to
CREATE (p) – [r:INTERESTED_IN] - - > (s);
-creo i lavori possibili
LOAD CSV WITH HEADERS FROM 'file:/projects.csv' AS row FIELDTERMINATOR ';'
CREATE (:work{name: row.name});
-creo che lavoro fanno le persone (quindi le relazioni)
LOAD CSV WITH HEADERS FROM 'file:/worked_on.csv' AS row FIELDTERMINATOR ';'
MATCH (p:person {name:row.from}), (w:work {name:row.to})
CREATE (p) – [r:WORKED_ON] -> (w);
-creo le compagnie
LOAD CSV WITH HEADERS FROM 'file:/company.csv' as row FIELDTERMINATOR ';'
CREATE (:company{name:row.name});
-creo la relazione tra le persone e le compagnie
LOAD CSV WITH HEADERS FROM 'file:/works_for.csv' as row FIELDTERMINATOR ';'
MATCH (p:person{name:row.from}),(c:company{name:row.to})
CREATE (p)-[r:WORKS_FOR]->(c);
RISULTATO che ho ottenuto:
[I nodi pozzo in questo grafo sono—skill—work—company]
Fino ad ora abbiamo solo creato (i nodi, le relazioni…) ora dobbiamo scrivere delle query
Approfondimento su come scrivere le query:
Come si fa una query?? Si definisce il pattern (il disegno) e poi si ragione per descrivere la soluzione,
piuttosto che dire come calcolare la soluzione.
1) Individuare tutti quei nodi che non hanno archi uscenti, ci sono dei nodi che sono cosiddetti “pozzo”
ossia dei nodi in cui l’arco che porta con sé l’informazione (relazione) una volta entrato non esce più
niente (un qualcosa che entra e rimane) (esempio: persone che non seguono nessuno su instagram,
persone che non interagiscono con nessuno).
Qual è la caratteristica di un nodo in cui qualcosa entra ma non esce, un buco nero. Matchare
qualcosa che non esiste
MATCH (n) - - > (m) n e m sono identificativi
WHERE not (m) - - > () Return m
spiegazione [PER OGNI NODO in relazione n con m TALE CHE NON ESISTE un nodo m –[relaz.]- > con qualcosa]
la proprietà della rete per cui il pattern (pattern è= tutti quei nodi che vanno da un nodo n ad un
nodo m) tale che non è vero che il nodo m abbia degli archi uscenti – > quindi m è un NODO POZZO
Con return m.name in questo modo
MATCH (n) - - > (m) ritorna il nome di quei nodi pozzo (il
WHERE not (m) - - > () Return m.name nome è una stringa) o nel formato json
Nel grafo è la relazione che comanda talmente tanto che si possono esprimere delle query che
individuano anche il verso della relazione, ingoing-degree e outgoing-degree.
2) Il graph DB lo schema lo ha o non lo ha?? Si lo ha, lo schema è free, esiste ma è libero di evolvere, lo
schema è indotto dal dato (ossia definito dal dato) cioè è libero di evolvere in base al dato.
→
CALL db.schema.visualization() per osservare lo schema del grafo
schema del grafo creato la scorsa lezione
→
3) Si possono utilizzare queste funzioni all’interno del graph db CRUDE, CREATE, READ, UPDATE,
DELETE
Path traversal
4) Scrivere la query che trova persone che lavorano per una certa compagnia e che hanno degli interessi
e trovare dei soggetti che lavorano nella medesima compagnia e hanno medesimi interessi (soggetti
che sono interscambiabili). MATCH p1=
(subject)-[:WORKS_FOR]->(company)
<-[:WORKS_FOR]-(person),
p2=(subject)-[:INTERESTED_IN]
->(interest)<-[:INTERESTED_IN]
-(person)
RETURN p1,p2
Approccio per scrivere le query disegnare il pattern, il pezzo di grafo che si vuole guardare. In modo da
capire cosa stiamo cercando (il pattern quando matcha è un sotto-grafo ossia una porzione di grafo).
Il pattern che abbiamo descritto ammette una simmetria (in questo esempio, pur essendo un grafo
diretto che per sua natura è asimmetrico).
• E’ possibile rompere le simmetrie, cioè in questo esempio ci sono due modi per scrivere la stessa
query e quello che ci chiediamo è: esiste un modo per eliminare una simmetria in un grafo diretto
che per sua natura è asimmetrico? SI ESISTE, trucco è quello di forzare il DBMS ad assegnare solo e
soltanto una persona (tra person e subject). Si deve forzare il DBMS con una proprietà, ed è quella di
utilizzare gli id auto-incrementali (con ogni nodo che ha un id che noi assegniamo).
RIMUOVERE LA SIMMETRIA attraverso il pattern matching
WHERE id(subject)>id(person)
Query completa senza la simmetria:
MATCH p1=
(subject)-[:WORKS_FOR]->(company)
<-[:WORKS_FOR]-(person), p2=(subject)-[:INTERESTED_IN]
->(interest)<-[:INTERESTED_IN] -(person)
WHERE id(subject)>id(person)
RETURN person.name, subject.name, interest.name
5) E’ possibile fare sullo schema a grafo delle aggregazioni?
Si è possibile, eredita nella seconda parte nel return, eredita potenzialmente le medesime operazioni
che si possono fare in SQL
MATCH p1= In questa parte si “calcola” il risultato
(subject)-[:WORKS_FOR]->(company) che vogliamo ottenere
<-[:WORKS_FOR]-(person), p2=(subject)-[:INTERESTED_IN]
->(interest)<-[:INTERESTED_IN] -(person)
WHERE id(subject)>id(person)
RETURN subject.name as first, In questa parte si specifica come
person.name as second, vogliamo visualizzare il dato che
count (interest) as score, abbiamo calcolato sopra
collect (interest.name) as interests_in_common
ORDER BY score desc →
Collezionare collect
[Come risultato si avrà una tabella!!] Si ottiene una tabella ma è stato molto semplice a scrivere la
query rispetto che nel paradigma relazionale SQL.
6) Se si utilizza PROFILE o EXPLAIN, Cypher dice come intende svolgere una query scritta dall’utente,
quindi stampa a video tutto il percorso e le operazione che svolge (IL COME)
PROFILE MATCH
(subject)-[:WORKS_FOR]->(company1),(person)-[:WORKS_FOR]->(company2),
(subject)-[:INTERESTED_IN]->(interest)<- [:INTERESTED_IN]-(person)
WHERE id(subject)>id(person)
RETURN subject.name as first,
person.name as second,
count(interest) as score,
collect(interest.name) as interests_in_common,
company1,company2
ORDER BY score desc
(Try also with EXPLAIN)
7) WITH, è un po’ come fare una sotto-query, serve ad individuare da quel momento in poi solo quello
che viene indicato dopo la with e buttare via tutto quello che è stato fatto prima. In questo esempio
all’inizio si matchano due persone in relazione con progetto, però poi voglio solo tenere in
considerazione le due persone e quindi utilizzo la WITH, da quel momento in poi mi interessa solo n
e n2. Infatti dopo la WITH è stato inserito un nuovo MATCH richiamando p, ma NON si riferisce al
progetto che è stato creato precedentemente
[esattamente come una query annidata in SQL]
MATCH f=(n:per