Recensione: MongoDB conquista il mondo

Se negli ultimi anni hai creato un'applicazione web di dimensioni medio-grandi, probabilmente hai considerato di basarla sullo stack LAMP o MEAN open source. Il vecchio stack LAMP utilizza il sistema operativo Linux, il server web Apache, il database relazionale MySQL e il linguaggio di programmazione PHP. MEAN utilizza il database NoSQL MongoDB, il framework per applicazioni web back-end Express, la piattaforma applicativa Angular e il runtime JavaScript Node.js. MEAN è essenzialmente uno stack JavaScript end-to-end. Linux non è esplicitamente menzionato nell'acronimo, ma di solito è il sistema operativo sotto Node.

In questa recensione, parlerò del database MongoDB, ora alla versione 4. MongoDB è un database operativo altamente scalabile disponibile sia nelle versioni open source che aziendali e può essere eseguito in locale o come servizio cloud gestito. Il servizio cloud gestito si chiama MongoDB Atlas.

MongoDB è di gran lunga il più popolare dei database NoSQL. Il suo modello di dati del documento offre agli sviluppatori una grande flessibilità, mentre la sua architettura distribuita consente una grande scalabilità. Di conseguenza, MongoDB viene spesso scelto per applicazioni che devono gestire grandi volumi di dati, che beneficiano della scalabilità orizzontale e che gestiscono strutture di dati che non si adattano al modello relazionale.  

Poiché MongoDB è appropriato per un'ampia varietà di casi d'uso, viene spesso proposto come sostituto dei database relazionali. Tuttavia, sebbene la libertà dai rigidi vincoli dello schema sia spesso vantaggiosa, è importante tenere presente che nessun database di documenti è una soluzione universale, nemmeno MongoDB.

Origini di MongoDB

L'azienda dietro MongoDB è stata fondata nel 2007 come 10gen da un team che era dietro DoubleClick, la società di pubblicità su Internet. La motivazione originale per il database MongoDB era essere in grado di gestire l'agilità e la scala richieste per la pubblicità su Internet. Come esempio di scala, DoubleClick offriva 400.000 annunci al secondo nel 2007 e faticava a funzionare con i database esistenti dell'epoca.

MongoDB è un archivio basato su documenti che ha anche un archivio basato su grafici implementato sopra di esso. Gli altri tipi di database NoSQL sono archivi di valori-chiave e archivi basati su colonne. Tutti i tipi di database NoSQL condividono la capacità di scalare in modi che non erano possibili nei database relazionali SQL del 2007, ma le diverse varietà di database NoSQL hanno diversi punti di forza, debolezza e casi d'uso.

Alcuni dei principali concorrenti NoSQL di MongoDB come database operativi sono Amazon DynamoDB (key-value store), Google Cloud BigTable (column store), Google Cloud Datastore (document store), Redis (in-memory, key-value store), Couchbase (valore-chiave multimodello e archivio documenti), DataStax / Cassandra (archivio colonne) e Azure Cosmos DB (multimodello che include un'opzione SQL e diversi archivi NoSQL).

Cos'è MongoDB?

MongoDB Inc. descrive MongoDB come "un database di documenti con la scalabilità e la flessibilità che desideri con le query e l'indicizzazione di cui hai bisogno". Per analizzarlo, dobbiamo prima comprendere la natura di un database di documenti, che è uno dei tipi di progettazione NoSQL.

Anziché archiviare dati fortemente tipizzati in tabelle normalizzate correlate con schemi fissi come un database relazionale, un database di documenti archivia i dati correlati in forma denormalizzata incorporati in documenti nome-valore simili a JSON. MongoDB realtà non memorizza JSON, tuttavia: MongoDB memorizza BSON (Binary JSON), che si estende la rappresentazione JSON (stringhe) per includere altri tipi come int, long, date, floating point, decimal128, e coordinate geospaziali, come mostrato nello schema seguente. I documenti BSON contengono uno o più campi e ogni campo contiene un valore di un tipo di dati specifico, inclusi array, dati binari e documenti secondari . BSON tiene traccia anche della dimensione di ogni documento, per consentire una ricerca efficiente.

MongoDB

La digitazione BSON alimenta l'indicizzazione dei campi. MongoDB può generare grafici multimodali, geospaziali, B-tree e indici full text su una singola copia dei dati, utilizzando il tipo di dati per generare il tipo corretto di indice. MongoDB ti consente di creare indici su qualsiasi campo del documento.

MongoDB

MongoDB include database, raccolte (tabelle), documenti (righe), campi (colonne), indici $lookupo documenti incorporati (join), chiavi primarie, una pipeline di aggregazione e transazioni. Per prestazioni migliori ed evitare la necessità di transazioni multi-documento, probabilmente vorrai utilizzare documenti secondari e array in MongoDB piuttosto che archiviare i tuoi dati in forma normalizzata come faresti in un database SQL.

MongoDB 4 ha avere transazioni multi-documento, il che significa che è ancora possibile ottenere proprietà ACID, anche se si dispone di normalizzare il vostro disegno di dati. Le versioni precedenti no.

Per quello che vale, i rappresentanti di MongoDB mi hanno detto che le transazioni di un unico documento gestiscono il 90% dei casi d'uso che richiedono proprietà ACID. Quando i clienti avevano bisogno di ACID per transazioni multi-documento prima della versione 4, fondamentalmente lo implementavano da soli a livello di applicazione.

Per impostazione predefinita, MongoDB utilizza schemi dinamici, a volte chiamati senza schema. I documenti in una singola raccolta non devono avere lo stesso insieme di campi e il tipo di dati per un campo può differire tra i documenti all'interno di una raccolta. Puoi modificare le strutture dei documenti in qualsiasi momento.

Tuttavia, è disponibile la governance dello schema. A partire da MongoDB 3.6, MongoDB supporta la convalida dello schema JSON. Per attivarlo, utilizza l' $jsonSchemaoperatore nell'espressione del validatore. La convalida avviene durante gli aggiornamenti e gli inserimenti.

Come puoi vedere nell'istantanea della documentazione e nello screenshot di MongoDB Atlas di seguito, MongoDB ha il proprio linguaggio di query, implementato nella shell Mongo, in 12 API del driver di lingua supportate (e molte altre dalla comunità), e nella GUI Compass e nel Scheda Collezioni Atlas (Esplora dati). Il linguaggio di query MongoDB non è affatto lo stesso di SQL, ma esiste una mappatura più o meno diretta tra i due. Dico "più o meno" perché i database relazionali non supportano i documenti incorporati, ma MongoDB sì. Non è necessariamente tutto buono, come vedrai nella prossima sezione.

MongoDB MongoDB

Il framework di aggregazione MongoDB utilizza operatori di pipeline che sono più o meno l'equivalente delle clausole SQL GROUP BYe WHERE. Ad esempio, la seguente query utilizza il database del gruppo utenti di MongoDB per elencare gli eventi passati e gli RSVP totali per ogni evento, nella shell Mongo:

> db.past_events.aggregate ([{'$ match': {'batchID': 101, 'event.status': 'past', 'event.group.urlname': {'$ in': ['Atlanta-MongoDB -User-Group "," Austin-MongoDB-User-Group "," Baltimore-MongoDB-Users-Group "," Bangalore-MongoDB-User-Group "," Belfast-MongoDB-User-Group "," Bergen-NoSQL "," Bordeaux-MongoDB-User-Group "," Boston-MongoDB-User-Group "]}}},

{'$ group': {'_id': {'urlname': '$ event.group.urlname', 'year': {'$ year': '$ event.time'}}, 'event_count': {' $ sum ': 1},' rsvp_count ': {' $ sum ':' $ event.yes_rsvp_count '}}},

{'$ project': {'_id': 0, 'group': '$ _id.urlname', 'year': '$ _id.year', 'event_count': 1, 'rsvp_count': 1}}])

La query utilizza la aggregatefunzione con i $match, $in, $group, $sum, e $projectgli operatori e restituisce il seguente:

{"event_count": 2, "rsvp_count": 27, "group": "Boston-MongoDB-User-Group", "year": 2017}

{"event_count": 5, "rsvp_count": 94, "group": "Boston-MongoDB-User-Group", "year": 2016}

{"event_count": 5, "rsvp_count": 231, "group": "Boston-MongoDB-User-Group", "year": 2015}

{"event_count": 3, "rsvp_count": 175, "group": "Boston-MongoDB-User-Group", "year": 2014}

{"event_count": 10, "rsvp_count": 489, "group": "Boston-MongoDB-User-Group", "year": 2013}

{"event_count": 12, "rsvp_count": 444, "group": "Boston-MongoDB-User-Group", "year": 2012}

{"event_count": 2, "rsvp_count": 118, "group": "Boston-MongoDB-User-Group", "year": 2011}

{"event_count": 6, "rsvp_count": 84, "group": "Atlanta-MongoDB-User-Group", "year": 2011}

{"event_count": 3, "rsvp_count": 74, "group": "Baltimore-MongoDB-Users-Group", "year": 2012}

{"event_count": 1, "rsvp_count": 5, "group": "Bergen-NoSQL", "year": 2015}

{"event_count": 15, "rsvp_count": 286, "group": "Atlanta-MongoDB-User-Group", "year": 2012}

{ "event_count" : 11, "rsvp_count" : 321, "group" : "Baltimore-MongoDB-Users-Group", "year" : 2013 }

{ "event_count" : 8, "rsvp_count" : 124, "group" : "Bangalore-MongoDB-User-Group", "year" : 2015 }

{ "event_count" : 6, "rsvp_count" : 381, "group" : "Bangalore-MongoDB-User-Group", "year" : 2013 }

{ "event_count" : 7, "rsvp_count" : 242, "group" : "Bangalore-MongoDB-User-Group", "year" : 2012 }

{ "event_count" : 13, "rsvp_count" : 233, "group" : "Atlanta-MongoDB-User-Group", "year" : 2013 }

{ "event_count" : 10, "rsvp_count" : 171, "group" : "Baltimore-MongoDB-Users-Group", "year" : 2014 }

{ "event_count" : 3, "rsvp_count" : 28, "group" : "Austin-MongoDB-User-Group", "year" : 2017 }

{ "event_count" : 2, "rsvp_count" : 52, "group" : "Austin-MongoDB-User-Group", "year" : 2016 }

{ "event_count" : 1, "rsvp_count" : 8, "group" : "Atlanta-MongoDB-User-Group", "year" : 2018 }

Type "it" for more

MongoDB also has a mapReduce function. The Compass GUI has an aggregation pipeline builder that makes creating queries such as the one above fairly straightforward.

MongoDB supports a range of server data consistency levels starting with read uncommitted and going to causal. Causal consistency was only added in version 3.6, and is also supported in client sessions. The client sets read and write concerns to specify the desired consistency level.

In MongoDB, un'operazione di scrittura è atomica a livello di un singolo documento, anche se l'operazione modifica più documenti incorporati all'interno di un singolo documento. Quando una singola operazione di scrittura (ad esempio db.collection.updateMany()) modifica più documenti, la modifica di ogni documento è atomica, ma l'operazione nel suo insieme non è atomica. A partire dalla versione 4.0, per le situazioni che richiedono l'atomicità per gli aggiornamenti di più documenti o la coerenza tra le letture di più documenti, MongoDB fornisce transazioni multi-documento per i set di repliche, a un costo in termini di prestazioni.