NoSQL i database sono emersi enormemente negli ultimi anni a causa della loro struttura meno vincolante, della progettazione di schemi scalabili e dell'accesso più rapido rispetto ai database relazionali tradizionali (RDBMS / SQL). MongoDB è un database NoSQL orientato ai documenti open source che memorizza i dati sotto forma di oggetti simili a JSON. È emerso come uno dei principali database grazie allo schema dinamico, all'elevata scalabilità, alle prestazioni ottimali delle query, all'indicizzazione più rapida e ad una comunità di utenti attiva.
Se provieni da uno sfondo RDBMS / SQL, la comprensione dei concetti NoSQL e MongoDB può essere un po 'difficile all'avvio perché entrambe le tecnologie hanno una modalità di rappresentazione dei dati molto diversa. Questo articolo ti guiderà a capire in che modo il dominio RDBMS / SQL, le sue funzionalità, i termini e il linguaggio di query si associano al database MongoDB. Mappando, intendo che se avessimo un concetto in RDBMS / SQL, vedremo quale è il suo concetto equivalente in MongoDB.
Inizieremo con la mappatura dei concetti relazionali di base come tabella, riga, colonna, ecc. E passeremo a discutere di indicizzazione e join. Quindi esamineremo le query SQL e discuteremo le corrispondenti query del database MongoDB. L'articolo presuppone che tu sia a conoscenza dei concetti di base del database relazionale e di SQL, perché in tutto l'articolo sarà posto ulteriore accento sulla comprensione di come questi concetti vengono mappati in MongoDB. Cominciamo.
Ogni database in MongoDB è costituito da raccolte equivalenti a un database RDBMS costituito da tabelle SQL. Ogni raccolta memorizza i dati sotto forma di documenti che è equivalente alle tabelle che memorizzano i dati in righe. Mentre una riga memorizza i dati nel suo set di colonne, un documento ha una struttura simile a JSON (nota come BSON in MongoDB). Infine, il modo in cui abbiamo le righe in una riga SQL, abbiamo campi in MongoDB. Di seguito è riportato un esempio di documento (riga di lettura) con alcuni campi (colonne di lettura) che memorizzano i dati dell'utente:
"_id": ObjectId ("5146bb52d8524270060001f3"), "age": 25, "city": "Los Angeles", "email": "[email protected]", "user_name": "Mark Hanks"
Questo documento è equivalente a una singola riga in RDBMS. Una raccolta è composta da molti di questi documenti proprio come una tabella è composta da molte righe. Si noti che ogni documento in una raccolta ha un unico _ID
campo, che è un campo di 12 byte che funge da chiave primaria per i documenti. Il campo viene generato automaticamente alla creazione del documento e viene utilizzato per identificare univocamente ciascun documento.
Per capire meglio i mapping, prendiamo un esempio di una tabella SQL utenti
e la sua struttura corrispondente in MongoDB. Come mostrato nella Figura 1, ogni riga nella tabella SQL si trasforma in un documento e ogni colonna in un campo in MongoDB.
Una cosa interessante da mettere a fuoco qui è che i diversi documenti all'interno di una collezione possono avere schemi diversi. Quindi, in MongoDB è possibile che un documento abbia cinque campi e che l'altro documento abbia sette campi. I campi possono essere facilmente aggiunti, rimossi e modificati in qualsiasi momento. Inoltre, non vi è alcun vincolo sui tipi di dati dei campi. Quindi, in un caso, un campo può contenere int
digita i dati e alla prossima istanza potrebbe contenere un schieramento
.
Questi concetti devono sembrare molto diversi dai lettori provenienti da background RDBMS dove le strutture delle tabelle, le loro colonne, i tipi di dati e le relazioni sono predefinite. Questa funzionalità per utilizzare lo schema dinamico ci consente di generare documenti dinamici in fase di esecuzione.
Ad esempio, considera i seguenti due documenti all'interno della stessa collezione ma con schemi diversi (Figura 2):
Il primo documento contiene i campi indirizzo
e dob
che non sono presenti nel secondo documento mentre il secondo documento contiene campi Genere
e occupazione
che non sono presenti nel primo. Immaginiamo che se avessimo progettato questa cosa in SQL, avremmo mantenuto quattro colonne aggiuntive per indirizzo
, dob
, Genere
e occupazione
, alcuni dei quali memorizzerebbero valori vuoti (o nulli) e quindi occuperebbero spazio non necessario.
Questo modello di schema dinamico è la ragione per cui i database NosSQL sono altamente scalabili in termini di design. Vari schemi complessi (gerarchici, strutturati ad albero, ecc.) Che richiedono un numero elevato di tabelle RDBMS possono essere progettati in modo efficiente utilizzando tali documenti. Un tipico esempio potrebbe essere quello di archiviare i post degli utenti, i loro mi piace, i commenti e altre informazioni associate sotto forma di documenti. Un'implementazione SQL per lo stesso avrebbe idealmente tabelle separate per l'archiviazione di post, commenti e Mi piace mentre un documento MongoDB può memorizzare tutte queste informazioni in un singolo documento.
Le relazioni in RDBMS sono ottenute usando relazioni primarie e straniere e interrogando chi usa i join. Non esiste una mappatura così semplice in MongoDB, ma le relazioni qui sono progettate usando documenti incorporati e di collegamento.
Considera un esempio in cui è necessario memorizzare le informazioni dell'utente e le informazioni di contatto corrispondenti. Un design SQL ideale avrebbe due tabelle, per esempio informazioni utente
e informazioni sui contatti
, con chiavi primarie id
e contact_id
come mostrato in Fig 3. Il informazioni sui contatti
la tabella conterrebbe anche una colonna ID utente
quale sarebbe la chiave esterna che collega al id
campo del informazioni utente
tavolo.
Ora vedremo come progetteremmo tali relazioni in MongoDB usando approcci di collegamento di documenti e documenti incorporati. Osserva che nello schema SQL, generalmente aggiungiamo una colonna (come id
e contact_id
nel nostro caso) che funge da colonna principale per quella tabella. Tuttavia, in MongoDB, generalmente usiamo il generato automaticamente _ID
campo come chiave primaria per identificare in modo univoco i documenti.
Questo approccio utilizzerà due raccolte, informazioni utente
e informazioni sui contatti
entrambi hanno il loro unico _ID
campi. Avremo un campo ID utente
nel informazioni sui contatti
documento che si riferisce al _ID
campo del informazioni utente
documento che mostra a quale utente corrisponde il contatto. (Vedi Fig 4) Si noti che in MongoDB, le relazioni e le loro operazioni corrispondenti devono essere gestite manualmente (ad esempio, attraverso il codice) in quanto non si applicano vincoli di chiave esterna e regole.
Il ID utente
campo nel nostro documento è semplicemente un campo che contiene alcuni dati e tutta la logica ad essa associata deve essere implementata da noi. Ad esempio, anche se ne inserirai alcuni ID utente
nel informazioni sui contatti
documento che non esiste nel informazioni utente
raccolta, MongoDB non ha intenzione di lanciare alcun errore dicendo che corrispondente ID utente
non è stato trovato nel informazioni utente
raccolta (a differenza di SQL dove questo sarebbe un vincolo di chiave esterna non valido).
Il secondo approccio è incorporare il informazioni sui contatti
documento all'interno del informazioni utente
documento come questo (Fig 5):
Nell'esempio sopra, abbiamo incorporato un piccolo documento di informazioni di contatto all'interno delle informazioni dell'utente. In modo simile, documenti di grandi dimensioni e dati gerarchici possono essere incorporati in questo modo per mettere in relazione le entità.
Inoltre, quale approccio utilizzare tra l'approccio Linking e Embedded dipende dallo scenario specifico. Se si prevede che i dati da incorporare diventino più grandi, è preferibile utilizzare l'approccio di collegamento piuttosto che l'approccio integrato per evitare che il documento diventi troppo grande. L'approccio integrato viene generalmente utilizzato nei casi in cui è necessario incorporare una quantità limitata di informazioni (come l'indirizzo nel nostro esempio).
Per riassumere, la seguente tabella (Fig 6) rappresenta le comuni relazioni che abbiamo discusso:
Ora che siamo a nostro agio con le mappature di base tra RDBMS e MongoDB, discuteremo di come il linguaggio di query usato per interagire con il database differisce tra loro.
Per le query MongoDB, supponiamo una raccolta utenti
con la struttura del documento come segue:
"_id": ObjectId ("5146bb52d8524270060001f3"), "post_text": "Questo è un post di esempio", "user_name": "mark", "post_privacy": "public", "post_likes_count": 0
Per le query SQL, assumiamo la tabella utenti
avere cinque colonne con la seguente struttura:
Discuteremo le domande relative alla creazione e modifica di collezioni (o tabelle), inserimento, lettura, aggiornamento e rimozione di documenti (o righe). Ci sono due query per ogni punto, uno per SQL e un altro per MongoDB. Spiegherò le query di MongoDB solo perché conosciamo abbastanza bene le query SQL. Le query MongoDB qui presentate sono scritte nella shell di Mongo JavaScript mentre le query SQL sono scritte in MySQL.
In MongoDB, non è necessario creare esplicitamente la struttura di raccolta (come facciamo per le tabelle che utilizzano a CREA TABELLA
query). La struttura del documento viene creata automaticamente quando si verifica il primo inserimento nella raccolta. Tuttavia, puoi creare una raccolta vuota usando createCollection
comando.
SQL: CREATE TABLE 'posts' ('id' int (11) NOT NULL AUTO_INCREMENT, 'post_text' varchar (500) NOT NULL, 'user_name' varchar (20) NOT NULL, 'post_privacy' varchar (10) NOT NULL, ' post_likes_count 'int (11) NOT NULL, PRIMARY KEY (' id ')) MongoDB: db.createCollection ("posts")
Per inserire un documento in MongoDB, usiamo il inserire
metodo che prende come oggetto un oggetto con coppie di valori chiave. Il documento inserito conterrà l'autogenerazione _ID
campo. Tuttavia, è anche possibile fornire esplicitamente un valore di 12 byte come _ID
insieme agli altri campi.
SQL: INSERT INTO 'posts' ('id', 'post_text', 'user_name', 'post_privacy', 'post_likes_count') VALUES (NULL, 'Questo è un esempio di post', 'marchio', 'pubblico', '0 '); MongoDB: db.posts.insert (user_name: "mark", post_text: "Questo è un esempio di post", post_privacy: "public", post_likes_count: 0)
Non c'è Alter Table
funzione in MongoDB per cambiare la struttura del documento. Poiché i documenti sono dinamici nello schema, lo schema cambia man mano che avviene un aggiornamento sul documento.
MongoDB usa il trova
metodo che è equivalente al SELEZIONARE
comando in SQL. Le seguenti affermazioni leggono semplicemente tutti i documenti dal messaggi
collezione.
SQL: SELECT * FROM 'posts' MongoDB: db.posts.find ()
La seguente query esegue una ricerca condizionale per i documenti nome utente
campo come marchio
. Tutti i criteri per il recupero dei documenti devono essere inseriti nelle prime parentesi separate da virgole.
SQL: SELECT * FROM 'posts' WHERE 'user_name' = 'mark' MongoDB: db.posts.find (user_name: "mark")
La seguente query recupera colonne specifiche, post_text
e post_likes_count
come specificato nella seconda serie di parentesi graffe .
SQL: SELECT 'post_text', 'post_likes_count' FROM 'posts' MongoDB: db.posts.find (, post_text: 1, post_likes_count: 1)
Si noti che MongoDB di default restituisce il _ID
campo con ogni dichiarazione di ritrovamento. Se non vogliamo questo campo nel nostro set di risultati, dobbiamo specificare il _ID
chiave con a 0
valore nell'elenco delle colonne da recuperare. Il 0
il valore della chiave indica che vogliamo escludere questo campo dal set di risultati.
MongoDB: db.posts.find (, post_text: 1, post_likes_count: 1, _id: 0)
La seguente query recupera campi specifici in base al criterio nome utente
è marchio
.
SQL: SELECT 'post_text', 'post_likes_count' FROM 'posts' WHERE 'user_name' = 'mark' MongoDB: db.posts.find (user_name: "mark", post_text: 1, post_likes_count: 1)
Ora aggiungeremo un altro criterio per recuperare i post con tipo di privacy come pubblico. I campi dei criteri specificati usando le virgole rappresentano la logica E
condizione. Quindi, questa affermazione cercherà i documenti che hanno entrambi nome utente
come marchio
e post_privacy
come pubblico
.
SQL: SELECT 'post_text', 'post_likes_count' FROM 'posts' WHERE 'user_name' = 'mark' AND 'post_privacy' = 'public' MongoDB: db.posts.find (user_name: "mark", post_privacy: "public" , post_text: 1, post_likes_count: 1)
Per usare logico O
tra i criteri in trova
metodo, usiamo il $ o
operatore.
SQL: SELECT 'post_text', 'post_likes_count' FROM 'posts' WHERE 'user_name' = 'mark' OR 'post_privacy' = 'public' MongoDB: db.posts.find ($ o: [user_name: "mark" , post_privacy: "pubblico"], post_text: 1, post_likes_count: 1)
Successivamente, useremo il ordinare
metodo che ordina il risultato in ordine crescente di post_likes_count
(indicato da 1).
SQL: SELECT * FROM 'posts' WHERE 'user_name' = 'mark' ordina per post_likes_count ASC MongoDB: db.posts.find (user_name: "mark"). Sort (post_likes_count: 1)
Per ordinare i risultati in ordine decrescente, specifichiamo -1
come valore del campo.
SQL: SELECT * FROM 'posts' WHERE 'user_name' = 'mark' ordina per post_likes_count DESC MongoDB: db.posts.find (user_name: "mark"). Sort (post_likes_count: -1)
Per limitare il numero di documenti da restituire, usiamo il limite
metodo che specifica il numero di documenti.
SQL: SELECT * FROM 'posts' LIMIT 10 MongoDB: db.posts.find (). Limit (10)
Il modo in cui usiamo compensare
in SQL per saltare un certo numero di record, usiamo Salta
funzione in MongoDB. Ad esempio, la seguente dichiarazione recupera dieci messaggi saltando i primi cinque.
SQL: SELECT * FROM 'posts' LIMIT 10 OFFSET 5 MongoDB: db.posts.find (). Limit (10) .skip (5)
Il primo parametro per aggiornare
metodo specifica i criteri per selezionare i documenti. Il secondo parametro specifica l'operazione di aggiornamento effettiva da eseguire. Ad esempio, la seguente query seleziona tutti i documenti con nome utente
come marchio
e imposta loro post_privacy
come privato
.
Una differenza qui è che per impostazione predefinita, MongoDB aggiornare
query aggiorna solo un documento (e il primo abbinato). Per aggiornare tutti i documenti corrispondenti dobbiamo fornire un terzo parametro che specifica Multi
come vero
indicando che vogliamo aggiornare più documenti.
SQL: UPDATE post SET post_privacy = "privato" WHERE user_name = "mark" MongoDB: db.posts.update (user_name: "mark", $ set: post_privacy: "private", multi: true )
La rimozione dei documenti è abbastanza semplice e simile a SQL.
SQL: DELETE FROM post WHERE user_name = "mark" MongoDB: db.posts.remove (user_name: "mark")
MongoDB ha un indice di default creato su _ID
campo di ogni collezione. Per creare nuovi indici sui campi, usiamo ensureIndex
metodo che specifica i campi e l'ordinamento associato indicato da 1
o -1
(crescente o decrescente).
SQL: CREATE INDEX index_posts ON posts (user_name, post_likes_count DESC) MongoDB: db.posts.ensureIndex (user_name: 1, post_likes_count: -1)
Per vedere tutti gli indici presenti in qualsiasi collezione, usiamo getIndexes
metodo sulla stessa linea di SHOW INDICE
query di SQL.
SQL: SHOW INDEX FROM post MongoDB: db.posts.getIndexes ()
In questo articolo, abbiamo capito come i concetti e i termini elementari di RDBMS / SQL si riferiscono a MongoDB. Abbiamo esaminato la progettazione delle relazioni in MongoDB e abbiamo appreso come funziona la funzionalità delle query SQL di base in MongoDB.
Dopo aver iniziato con questo articolo, puoi continuare a provare query complesse che includono aggregazione, riduzione della mappa e query che coinvolgono più raccolte. Puoi anche prendere l'aiuto di alcuni strumenti online per convertire le query SQL in query MongoDB all'inizio. Puoi giocare da solo a progettare uno schema di database MongoDB di esempio. Uno dei migliori esempi per farlo sarebbe un database per archiviare i post degli utenti, i loro mi piace, i commenti e i mi piace di commenti. Questo ti darebbe una visione pratica del design flessibile dello schema offerto da MongoDB.
Sentiti libero di commentare qualsiasi suggerimento, domanda o idea che vorresti vedere ulteriormente.