![](https://i.imgur.com/HLyXUzm.png) ## Domande Complementi Basi di dati: ### CAP theorem È impossibile per un sistema distribuito garantire contemporaneamente: - **C**onsistency: tutti i nodi vedono gli stessi dati contemporaneamente. - **A**vailability: Ogni richiesta deve ricevere una risposta - **P**artition tolerance: il sistema continua ad operare nonostante un malfunzionamento in una parte di esso I sistemi RDBMS sono **CA**, MongoDB è **CP**, tra i sistemi **AP** ci sono Dynamo e Cassandra. ### Mongo DB Un'alternativa al modello relazionale sono i modelli document-based, ossia documenti indirizzati all'interno di una collezione tramite una chiave. Caratteristiche: - N-Dimensional storage. - Il valore di ogni campo può corrispondere ad 0, 1 o più valori. - Le query posso essere effettuate ad ogni livello. - Schema flessibile: non tutti gli attributi devono essere necessariamente presenti all'interno di ogni documento. Il collegamento dei dati può essere eseguito in 2 modi: 1. **referencing:** le informazioni relative ad un campo sono contenute all'interno di un altro documento del quale viene memorizzato l'id. Tale approccio evita la duplicazione dei dati e mantiene uno schema più flessibile. Sono necessarie però query aggiuntive per risolvere le referenze. 2. **embedding:** le informazioni principali relative ad un campo sono memorizzate all'interno di un documento memorizzato come valore di tale campo (particolarmente utile per le relazioni one-to-many). Tale soluzione sveltisce le operazioni di read e permette di aggiornare dati collegati in una sola operazione, la crescita del documento può però portare ad un rallentamento delle operazioni di scrittura. MongoDB è uno dei linguaggi principali per la gestione e l'interrogazione di una base di dati document-based. Garantisce scalabilità orizzontale tramite l'utilizzo di shards. #### Sintassi: - query generica: ``` db.collection.find( <-collection {field1 : value, field2 : value} <- query criteria {field3 : 1, field4 : 0} <- projection .limit().sort() <- cursor modifiers ``` - Proiezioni: - Escludere un elemento: `db.collection.find({condition}{filed1 : 0})` - Includere 2 campi e l'attributo _id `db.collection.find({condition},{filed1 : 1, field2 : 1})` - Includere 2 campi senza l'atributo _id `db.collection.find({condition},{filed1 : 1, field2 : 1, _id : 0})` - Queries: - Selezionare tutti i documenti `db.collection.find()` - Condizione di uguaglianza `db.collection.find({field : x})` - In operator `db.collection.find({field : {$in [x, y]}})` - And operator `db.collection.find({field1 : x, field2 : y})` - Or condition `db.collection.find({$or : [{field1 : x}, {field2 : y}]})` - Exact match on embedded document (Devono essere presenti solo tali attributi ed in questo ordine): `db.collection.find({field : {sub_field1 : x, subfield2 : y}})` - Exact match on array `db.collection.find({array : [x, y, z]})` - Match su un elemento dell'array (basta che x sia presente in qualsiasi posizione) `db.collection.find({array : x})` - Match a specific element of an array `db.collection.find(array.posizione : x)` - Match campi multipli (trova i documenti dove il campo arr è un array che contiene almeno un elemento con campo field1 uguale a x ed almeno un elemento con campo field2 uguale a y) `db.collection.find({arr.field1 : x, arr.field2 : y})` - Match campi multipli (trova i documenti dove il campo arr è un array che contiene almeno un elemento che ha il campo field1 uguale a ed il campo field2 uguale a y) `db.collection.find({arr : {$elemMatch : {field1 : x, field2 : y}}})` - Inserimenti `db.collection.insertOne({field1 : x, field2 : y, field3 : z})` - Aggiornamenti - Aggiornamenti multupli `db.collection.updateMany({field1 : x, field2 : y}{$set : {field3 : z}})` - Aggiornamento con inserimento(se non esiste nessun documento che rispetta tali condizioni lo inserisce) `db.collection.updateOne({field1 : x, field2 : y}{$set : {field3 : z}}{upsert : true})` - Rimozioni `db.collection.deleteMany({field1 : x, field2 : y})` - Aggregazioni ``` db.collection.aggregate([ $match stage -> {$match : {field : value}}, //Mantiene solo i documenti in cui field = value $group stage -> {$group {newfield1 : "$fieldx", newfield2 : {$sum : "$fieldy"}}} // raggruppa i documenti per il valore di fieldx e chiama tala campo newfield1 // per ogni gruppo memorizza la somma di fieldy in newfield2 ]) ``` ### GraphDB I dati sono memorizzati e gestiti sottoforma di grafo. Ci sono principalmente 2 modi per gestirli: - Graph Database: un DBMS che gestisce in maniera persistente un grafo - Graph Compute engines: tecnologie per l'analisi offline dei grafi I GraphDB supportano le operazioni CRUD e le interrogazioni corrispondono ad attraversamenti del grafo, sono altamente performanti. **Storage:** - Nativo: la memorizzazione è ottimizzata per la progettazione e la gestione dei dati. Per ogni nodo memorizzo i suoi attributi ed a quali nodi è connesso - Non nativo: Trasformo i dati dal formato grafo ad un altro formato(relazionale/object oriented/...) e li memorizzo in tale formato. **Processing engine:** - Nativo: Index free adjency: è possibile accedere ai vicini di uno nodo istantaneamente, senza passare per indici esterni, così facendo si rende l'attraversamento molto efficiente rallentando leggermente le operazioni di scrittura. - Non nativo: è necessario riferirsi ad un indice di look-up come nel caso degli RDBMS, tale soluzione non è minimamente efficiente per certe query: cercando di trovare gli amici degli amici degli amici di Anna genero un join-bomb. Nei database a grafo è possibile effettuare transazioni rispettando le proprietà acide. I database a grafo scalano in modo efficiente in orizzontale. A differenza dei sistemi RDMBS la dimensione totale della base di dati non influisce pesantemente sui tempi di risposta in quanto gli indici sono utilizzati solo per trovare il nodo iniziale. Utilizzando graphDB è possibile memorizzare grandi quantità di dati. Per poter interrogare i database a grafo servono linguaggi appositi: **Cypher** - Pattern-matching query language - Human language - Expressive - Declarative: scegli cosa vuoi, non come - Permette aggregazioni, ordinamenti e limit - Permette di poter aggiornare il grafo Idea generale: i nodi sono espressi tra () mentre gli archi sono rappresentati usando -[]- / -[]-> / <-[]-. Una query consiste nel selezionare le parti di un grafo(nodi e archi) che rispettano determinate proprietà per poi restiruire le informazioni richieste. **Sintassi:** ```sql= MATCH conditions RETURN info we need ORDER BY field LIMIT number of results ``` - Clausola MATCH: ```sql= MATCH (node1 : type_node1) -[:rel_type]->(node2 : type_node2) ``` Stiamo cercando di tutti quei nodi di tipo `type_node1` che hanno un arco uscente di tipo `rel_type` verso un nodo di tipo `type_node2`, invertendo la freccia cambiamo il verso dell'arco: ```sql= MATCH (node1 : type_node1) <-[:rel_type]-(node2 : type_node2) ``` Mentre non mettendo < o > troviamo sia gli archi uscenti sia quelli entranti: ```sql= MATCH (node1 : type_node1) -[:rel_type]-(node2 : type_node2) ``` Se l'arco non deve essere di nessun tipo basta escludere le [] : ```sql= MATCH (node1 : type_node1) --> (node2 : type_node2) ``` È possibile specificare che gli attributi dei nodi rispecchino determinati valori: ```sql= MATCH (node1 : type_node1 {field : value}) -[:rel_type]-> (node2 : type_node2) ``` È possibile dare un nome agli archi per poi utilizzarli nella clausola WHERE ```sql= MATCH (node1) -[rel : rel_type]- (node2) WHERE rel.field = value ``` - Clausola RETURN: Uno o più nodi: ```sql= MATCH (node1 : type_node1) -[:rel_type]->(node2 : type_node2) RETURN node1, node2 ``` Proprietà dei nodi: ```sql= MATCH (node1 : type_node1) -[:rel_type]->(node2 : type_node2) RETURN node1.property1, node2.property2 ``` Usando DINSTICT evitiamo i duplicati ```sql= MATCH (node1 : type_node1) -[:rel_type]->(node2 : type_node2) RETURN DISTINCT node1.property1 ``` Usando OPTIONAL aggiungiamo una condizione che non necessariamente deve essere rispettata, ma nel caso in cui lo sia aggiugne informazioni ```sql= MATCH (node1 : typenode1 {field : value}) -[:rel_type]-> (node2 : typenode2) OPTIONAL MATCH (node1) -[:rel_type2]-> (node3) ``` - Clausole ORDER BY e LIMIT ```sql= MATCH (node1 : type_node1) -[:rel_type]->(node2 : type_node2) RETURN node1.property1, node2.property2 ORDER BY node1.property3 DESC LIMIT 10 ``` - Create Creare un semplice nodo: ```sql= CREATE (you:Person {name:"You"}) RETURN you ``` Creare una relazione: ```sql= MATCH (you:Person {name:"You"}) CREATE (you)-[like:LIKE]->(neo:Database {name:"Neo4j" }) RETURN you,like,neo ``` Creare più relazioni contemporaneamente: ```sql= MATCH (you:Person {name:"You"}) FOREACH (name in ["Johan","Rajesh","Anna","Julia","Andrew"] | CREATE (you)-[:FRIEND]->(:Person {name:name})) ``` - shorthest path: p è il percorso minimo tra "you" e qualcuno che ha lavorato con neo4j ammettendo al più 5 archi ```sql= MATCH (you {name:"You"}), (expert)-[:WORKED_WITH]- >(neo:Database {name:"Neo4j"}), p = shortestPath( (you)-[:FRIEND*..5]-(expert) ) RETURN p,neo ``` ### RDF: Resource Description Framework Modello per la rappresentazione dati, si basa su triple (soggetto | predicato | oggetto). Tali triple sono organizzate in grafi orientati (i predicati rappresentano gli archi, mentre soggetto ed oggetto i nodi) dove ogni oggetto è identificato unicamente sul web da un uri. Caratteristiche: - Indipendenza: i predicati sono risorse, ogni organizzazione indipendente può creare le proprie - Interchage: facilmente convertibili - Scalabili - Le proprietà sono risorse, quindi anche esse hanno le loro proprietà - Soggetto ed oggetto possono essere risorse Esistono diverse rappresentazioni per triple RDF: 1. Notazione XML: organizzata ```xml= <rdf:RDF a xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/"> <rdf:Description rdf:about="http://www.archeoserver.it"> <dc:title>Sharing archaeological knowledge on the web</dc:title> </rdf:Description> </rdf:RDF> ``` 2. Turtle/N3 notation: molto più compatta e leggibile: fromato `soggetto predicato oggetto .` ```xmlk @prefix dc: <http://purl.org/dc/elements/1.1/> . <http://www.archeoserver.it/home.html> dc:title "Sharing archaeological knowledge on the web". ``` Triple con lo stesso soggetto possono essere abbreviate con ; ```xmlk @prefix dc: <http://purl.org/dc/elements/1.1/> . <http://www.archeoserver.it/> dc:title "Sharing archaeological knowledge on the web" ; dc:publisher “UniBo” ; ``` Triple con lo stesso soggetto e predicato possono essere abbreviate con , ```xmlj @prefix dc: <http://purl.org/dc/elements/1.1/> . <http://www.archeoserver.it/> dc:title "Sharing archaeological knowledge on the web"@en , “Condividi la conoscenza archeologia sul web”@it ; ``` **RDF_Schema:** Linguaggio che può essere utilizzato per definire vocabolari. Indica che stiamo descrivendo specifici tipi o classi di oggetti. I concetti di RDFS sono essi stessi memorizzati come un vocabolario RDF. - Per definire delle classi: `C rdf:type rdfs:Class` - Per definre il tipo di un oggetto specifico `X rdf:type C` - Per definire sottoclassi (proprietà riflessiva e transitiva): `A rdfs:subClassOf B` - `rdfs:domain` indica a quali classi va assegnata una certa proprietà - `rdfs:range` definisce il tipo di valore da assegnare ad una certa proprietà **Linked data:** è un metodo per pubblicare dati strutturati tramite vocabolari, che possono essere connessi ed intepretati da macchine. Usando linked data, i dati forniti in triple possono essere memorizzati in siti diversi. Ogni oggetto è identificato da un URI nel web. **SPARQL:** SQL-like query language per RDF **Sintassi:** - Order by / limit ``` SELECT ... FROM ... WHERE { ... } ORDER BY ASC (?field) LIMIT rows ``` - Filter ``` SELECT ... FROM ... WHERE { ... FILTER(cond). } ``` - Filter per controllare la lingua ``` SELECT ... FROM ... WHERE { ... FILTER(LANG(?field) = 'en'). } ``` - Optional ``` SELECT ?a, ?b FROM ... WHERE { ?a ... OPTIONAL { ... ?b } } ``` - Union ``` SELECT ... FROM ... WHERE { {} UNION {} } ``` - Bound (Ricerca tutti gli autori che non hanno un notable work) ``` SELECT ?author FROM <http://dbpedia.org/> WHERE { ?author rdf:type dbo:Writer . OPTIONAL {?author dbo:notableWork ?work . } FILTER (!BOUND(?work)) . } ``` - Count / Group by / having ``` SELECT ?author COUNT(?work) AS ?num_works FROM <http://dbpedia.org/> WHERE { ?author rdf:type dbo:Writer ; dbo:notableWork ?work . } GROUP BY ?author HAVING (COUNT(?work) = 3) ``` - Distinct ``` SELECT DISTINCT(?x) FROM ... WHERE { ... } ``` - Ask ``` ASK WHERE { ... } ``` ### Data quality Qualità: caratteristica di un artifatto di soddisfare le necessità implicite o esplicite di chi usa tale dato. Spesso difficile valutare: vengono usate delle metriche per stimare tale qualità. Possibili dimensioni di qualità: - Precisione - Completezza - Consistenza - Leggibilità - Usabilità - Volatilità Per ogni dimensione bisognrebbe definire una metrica per valutarne la qualità: - Accuratezza/Precisione: vicinanza tra il valore memorizzato e quello reale. L'accuratezza può essere sintattica o semantica, la prima è più semplice da controllare. Una possibile metrica per la precisione è la distanza di edit: numero di inserimenti/cancellazioni/sostituzioni necessari per trasformare la prima stringa nella seconda(Esiste anche la versione normalizzata in cui la precisione viene rappresentata come ```1 - ED(s1, s2)/N``` (N sono i caratteri della stringa più lunga) : più tale valore è vicino ad 1 e più il dato è preciso). - Completezza: si misura come numero di valori nulli rispetto al numero di valori totali - Proprietà temporali: i dati devono essere aggiornati, la currency misura il tempo con cui i dati vengono aggiornati. Un primo esempio di currency è il ritardo tra il tempo t1 dell'evento nel mondo reale e l'istante t2 in cui viene aggiornato nel sistema informativo. - Consistenza: 1. I dati devono rispettare le regole di integrità (il valore di un CAP deve essere valido per una città. 2. Consistenza delle diverse rappresentazioni dello stesso oggetto. Record linkage: capire se 2 descrizioni differenti descrivono lo stesso oggetto in 2 file differenti. Deduplication: un problema simile al record linkage: consiste nel cercar di capire se dati all'interno della tabella sono duplicati.