MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Introduzione ai tipi di dati MongoDB


Introduzione

Quando usi MongoDB, hai la possibilità di essere flessibile con la struttura dei tuoi dati. Non sei vincolato al mantenimento di un determinato schema in cui tutti i tuoi documenti devono rientrare. Per ogni dato campo in un documento, puoi utilizzare uno qualsiasi dei tipi di dati disponibili supportato da MongoDB. Nonostante questo modo di lavorare predefinito, puoi imporre uno schema JSON in MongoDB per aggiungere la convalida alle tue raccolte, se lo desideri. Non entreremo nei dettagli della progettazione dello schema in questa guida, ma può avere un effetto sulla tipizzazione dei dati se implementata.

I tipi di dati specificano un modello generale per i dati che accettano e archiviano. È fondamentale capire quando scegliere un determinato tipo di dati rispetto a un altro quando si pianifica il database. Il tipo scelto determinerà come puoi operare sui tuoi dati e come vengono archiviati.



JSON e BSON

Prima di entrare nei dettagli di tipi di dati specifici, è importante comprendere come MongoDB archivia i dati. MongoDB e molti altri database NoSQL basati su documenti utilizzano JSON (JavaScript Object Notation) per rappresentare i record di dati come documenti.

Ci sono molti vantaggi nell'usare JSON per archiviare i dati. Alcuni di loro sono:

  • facilità di lettura, apprendimento e familiarità tra gli sviluppatori
  • flessibilità nel formato, sparso, gerarchico o profondamente nidificato
  • Autodescrittivo, che consente alle applicazioni di operare facilmente con i dati JSON
  • consente di concentrarsi su un numero minimo di tipi di base

JSON supporta tutti i tipi di dati di base come stringa, numero, booleano, ecc. MongoDB archivia effettivamente i record di dati come documenti JSON (BSON) con codifica binaria. Come JSON, BSON supporta l'incorporamento di documenti e array all'interno di altri documenti e array. BSON consente tipi di dati aggiuntivi che non sono disponibili per JSON.



Quali sono i tipi di dati in MongoDB?

Prima di entrare nei dettagli, diamo una visione generale di quali tipi di dati sono supportati in MongoDB.

MongoDB supporta una gamma di tipi di dati adatti a vari tipi di dati sia semplici che complessi. Questi includono:

Testo

  • String

Numerico

  • 32-Bit Integer
  • 64-Bit Integer
  • Double
  • Decimal128

Data/Ora

  • Date
  • Timestamp

Altro

  • Object
  • Array
  • Binary Data
  • ObjectId
  • Boolean
  • Null
  • Regular Expression
  • JavaScript
  • Min Key
  • Max Key

In MongoDB, ogni tipo BSON ha identificatori sia intero che stringa. Tratteremo i più comuni di questi in modo più approfondito in questa guida.



Tipi di stringhe

Il tipo di stringa è il tipo di dati MongoDB più comunemente utilizzato. Qualsiasi valore scritto tra virgolette "" in JSON è un valore stringa. Qualsiasi valore che desideri venga archiviato come testo sarà meglio digitato come String . Le stringhe BSON sono UTF-8 e sono rappresentate in MongoDB come:

        Type         | Number |  Alias   |  ------------------ | ------ | -------- |       String        |    2   | "string" |

In genere, i driver per i linguaggi di programmazione vengono convertiti dal formato stringa del linguaggio a UTF-8 durante la serializzazione e la deserializzazione di BSON. Questo rende BSON un metodo interessante per memorizzare facilmente i caratteri internazionali, ad esempio.

Inserimento di un documento con una String il tipo di dati sarà simile a questo:

db.mytestcoll.insertOne({first_name: "Alex"}){        "acknowledged": true,        "insertedId": ObjectId("614b37296a124db40ae74d15")}

Interrogare la raccolta restituirà quanto segue:

db.mytestcoll.find().pretty(){        _id: ObjectId("614b37296a124db40ae74d15"),         first_name: "Alex"}

Utilizzo del $type operatore

Prima di passare al nostro prossimo tipo di dati, è importante sapere come digitare controlla il valore prima di effettuare qualsiasi inserimento. Useremo l'esempio precedente per dimostrare l'uso del $type operatore in MongoDB.

Diciamo che è passato un po' di tempo da quando abbiamo lavorato con mytestcoll raccolta di prima. Vogliamo inserire alcuni documenti aggiuntivi nella raccolta con il first_name campo. Per verificare che abbiamo usato String come tipo di dati archiviato come valore di first_name originariamente, possiamo eseguire quanto segue utilizzando l'alias o il valore numerico del tipo di dati:

db.mytestcoll.find( { "first_name": { $type: "string" } } )

Oppure

db.mytestcoll.find( { "first_name": { $type: 2 } } )

Entrambe le query restituiscono un output di tutti i documenti che hanno una String valore memorizzato per first_name dall'inserimento della nostra sezione precedente:

[ { _id: ObjectId("614b37296a124db40ae74d15"), first_name: "Alex" } ]

Se richiedi un tipo che non è memorizzato nel first_name campo di qualsiasi documento, non otterrai alcun risultato. Ciò indica che si tratta di un altro tipo di dati archiviato in first_name .

Puoi anche eseguire query per più tipi di dati alla volta con il $type operatore come il seguente:

db.mytestcoll.find( { "first_name": { $type: ["string", "null"] } } )

Perché non abbiamo inserito alcun Null digita i valori nella nostra raccolta, il risultato sarà lo stesso:

[ { _id: ObjectId("614b37296a124db40ae74d15"), first_name: "Alex" } ]

Puoi utilizzare lo stesso metodo con tutti i seguenti tipi di cui parleremo.




Numeri e valori numerici

MongoDB include una gamma di tipi di dati numerici adatti a diversi scenari. La decisione del tipo da utilizzare dipende dalla natura dei valori che prevedi di archiviare e dai casi d'uso per i dati. JSON chiama qualsiasi cosa con numeri un Numero . Ciò costringe il sistema a capire come trasformarlo nel tipo di dati nativo più vicino. Inizieremo esplorando gli interi e come funzionano in MongoDB.


Intero

Il Integer il tipo di dati viene utilizzato per memorizzare i numeri come numeri interi senza frazioni o decimali. Gli interi possono essere valori positivi o negativi. Esistono due tipi in MongoDB, 32-Bit Integer e 64-Bit Integer . Possono essere rappresentati nei due modi illustrati nella tabella seguente, number e alias :

  Integer type   | number |    alias     |   ------------   | -----  | ------------ |  `32-bit integer`|   16   |    "int"     | `64-bit integer`|   18   |    "long"    |

Gli intervalli in cui un valore può rientrare per ogni tipo sono i seguenti:

  Integer type   |    Applicable signed range     |    Applicable unsigned range    |  ------------   | ------------------------------ | ------------------------------- | `32-bit integer`| -2,147,483,648 to 2,147,483,647|  0 to 4,294,967,295             | `64-bit integer`| -9,223,372,036,854,775,808 to  |  0 to 18,446,744,073,709,551,615                         9,223,372,036,854,775,807

I tipi sopra sono limitati dal loro intervallo valido. Qualsiasi valore al di fuori dell'intervallo genererà un errore. Inserimento di un Integer digita in MongoDB sarà simile al seguente:

db.mytestcoll.insertOne({age: 26}){        "acknowledged": true,        "insertedId": ObjectId("614b37296a124db40ae74d14")}

E trovare il risultato restituirà quanto segue:

db.mytestcoll.find().pretty(){        _id: ObjectId("614b37296a124db40ae74d14"), age: 26}

Come suggerito dai nomi, un 32-Bit Integer ha 32 bit di precisione intera, utile per valori interi più piccoli che non si desidera memorizzare come sequenza di cifre. Aumentando la dimensione del numero, puoi aumentare fino al 64-Bit Integer che ha 64 bit di precisione intera e si adatta allo stesso caso d'uso del primo.



Doppio

In BSON, la sostituzione predefinita per il Numero di JSON è il Double tipo di dati. Il Double il tipo di dati viene utilizzato per memorizzare un valore a virgola mobile e può essere rappresentato in MongoDB in questo modo:

        Type         | Number |   Alias  |  ------------------ | ------ | -------- |       Double        |    1   | "double" |

I numeri in virgola mobile sono un altro modo per esprimere i numeri decimali, ma senza una precisione esatta e coerente.

I numeri in virgola mobile possono funzionare con un numero elevato di decimali in modo efficiente ma non sempre esattamente. Quello che segue è un esempio di inserimento di un documento con il Double digita nella tua raccolta:

db.mytestcoll.insertOne({testScore: 89.6}){        "acknowledged": true,        "insertedId": ObjectId("614b37296a124db40ae74d13")}

Possono esserci lievi differenze tra input e output durante il calcolo con doppi che potrebbero potenzialmente portare a comportamenti imprevisti. Quando si eseguono operazioni che richiedono valori esatti, MongoDB ha un tipo più preciso.



Decimal128

Se stai lavorando con numeri molto grandi con molti intervalli in virgola mobile, allora Decimal128 Il tipo di dati BSON sarà l'opzione migliore. Questo sarà il tipo più utile per i valori che richiedono molta precisione, come nei casi d'uso che coinvolgono operazioni monetarie esatte. Il Decimal128 il tipo è rappresentato come:

        Type         | Number |   Alias   |  ------------------ | ------ | --------- |      Decimal128     |   19   | "decimal" |

Il tipo BSON, Decimal128 , fornisce 128 bit di rappresentazione decimale per la memorizzazione di numeri in cui è importante arrotondare esattamente i decimali. Decimal128 supporta 34 cifre decimali di precisione o un sinificando con un intervallo da -6143 a +6144. Ciò consente un'elevata precisione.

Inserimento di un valore utilizzando il Decimal128 il tipo di dati richiede l'utilizzo di NumberDecimal() costruttore con il tuo numero come String per impedire a MongoDB di utilizzare il tipo numerico predefinito, Double .

Qui, lo dimostriamo:

db.mytestcoll.insertOne({price : NumberDecimal("5.099")}){        "acknowledged": true,        "insertedId": ObjectId("614b37296a124db40ae74d12")}

Quando si interroga la raccolta, si ottiene il seguente ritorno:

db.mytestcoll.find().pretty(){        _id: ObjectId("614b37296a124db40ae74d12"),         price: "5.099" }

Il valore numerico mantiene la sua precisione consentendo operazioni esatte. Per dimostrare il Decimal128 digitare contro il Double , possiamo eseguire il seguente esercizio.



Come si può perdere la precisione in base al tipo di dati

Supponiamo di voler inserire un numero con molti valori decimali come Double in MongoDB con quanto segue:

db.mytestcoll.insertOne({ price: 9999999.4999999999 }){        "acknowledged": true,        "insertedId": ObjectId("614b37296a124db40ae74d24")}

Quando eseguiamo una query per questi dati, otteniamo il seguente risultato:

db.mytestcoll.find().pretty(){        _id: ObjectId("614b37296a124db40ae74d24"),         price: 9999999.5}

Questo valore arrotonda per eccesso a 9999999.5 , perdendo il valore esatto con cui l'abbiamo inserito. Questo rende Double inadatto per la memorizzazione di numeri con molti decimali.

Il prossimo esempio mostra dove la precisione andrà persa quando si passa un Double implicitamente con Decimal128 invece di una String come nell'esempio precedente.

Iniziamo inserendo il seguente Double di nuovo ma con NumberDecimal() per renderlo un Decimal128 digita:

db.mytestcoll.insertOne({ price: NumberDecimal( 9999999.4999999999 ) }){        "acknowledged": true,        "insertedId": ObjectId("614b37296a124db40ae74d14")}

Nota :Quando si effettua questo inserimento nella shell di MongoDB, viene visualizzato il seguente messaggio di avviso:

Warning: NumberDecimal: specifying a number as argument is deprecated and may lead to loss of precision, pass a string instead

Questo messaggio di avviso indica che il numero che stai tentando di passare potrebbe subire una perdita di precisione. Suggeriscono di usare una String usando NumberDecimal() in modo da non perdere alcuna precisione.

Se ignoriamo l'avviso e inseriamo comunque il documento, la perdita di precisione si vede nei risultati della query dall'arrotondamento per eccesso del valore:

db.mytestcoll.find().pretty(){        _id: ObjectId("614b37296a124db40ae74d14"),         price: Decimal128("9999999.50000000")}

Se seguiamo il NumberDecimal() consigliato avvicinarsi usando una String vedremo i seguenti risultati con precisione mantenuta:

db.mytestcoll.insertOne({ price: NumberDecimal( "9999999.4999999999" ) } )
db.mytestcoll.find().pretty(){        _id: ObjectId("614b37296a124db40ae74d14"),         price: Decimal128("9999999.4999999999")}

Per qualsiasi caso d'uso che richieda valori precisi ed esatti, questo ritorno potrebbe causare problemi. Qualsiasi lavoro che coinvolga operazioni monetarie è un esempio in cui la precisione sarà estremamente importante e avere valori esatti è fondamentale per calcoli accurati. Questa dimostrazione mette in evidenza l'importanza di sapere quale tipo di dati numerico sarà più adatto per i tuoi dati.




Data

Il BSON Date il tipo di dati è un numero intero a 64 bit che rappresenta il numero di millisecondi dall'epoca di Unix (1 gennaio 1970). Questo tipo di dati memorizza la data o l'ora corrente e può essere restituito come oggetto data o come stringa. Date è rappresentato in MongoDB come segue:

        Type         | Number |     Alias    |  ------------------ | ------ | ------------ |        Date         |    9   |     "date"   |

Nota :BSON Date il tipo è firmato. I valori negativi rappresentano date precedenti al 1970.

Esistono tre metodi per restituire i valori di data.

  1. Date() - restituisce una stringa

  2. new Date() - restituisce un oggetto data utilizzando ISODate() involucro

  3. ISODate() - restituisce anche un oggetto data utilizzando ISODate() involucro

Dimostriamo queste opzioni di seguito:

var date1 = Date()var date2 = new Date()var date3 = ISODate()db.mytestcoll.insertOne({firstDate: date1, secondDate: date2, thirdDate: date3}){        "acknowledged": true,        "insertedId": ObjectId("614b37296a124db40ae74d22")}

E al ritorno:

db.mytestcoll.find().pretty(){                "_id" : ObjectId("614b37296a124db40ae74d22"),                firstDate: 'Tue Sep 28 2021 11:28:52 GMT+0200 (Central European Summer Time)',                secondDate: ISODate("2021-09-28T09:29:01.924Z"),                thirdDate: ISODate("2021-09-28T09:29:12.151Z")}


Timestamp

C'è anche il Timestamp tipo di dati in MongoDB per rappresentare l'ora. Tuttavia, Timestamp sarà molto utile per uso interno e non lo è associato alla Date genere. Il tipo stesso è una sequenza di caratteri utilizzata per descrivere la data e l'ora in cui si verifica un evento. Timestamp è un valore a 64 bit dove:

  • i 32 bit più significativi sono time_t valore (secondi dall'epoca di Unix)
  • i 32 bit meno significativi sono un ordinal incrementale per operazioni entro un dato secondo

La sua rappresentazione in MongoDB avrà il seguente aspetto:

        Type         | Number |     Alias    |  ------------------ | ------ | ------------ |      Timestamp      |   17   |  "timestamp" |

Quando si inserisce un documento che contiene campi di primo livello con timestamp vuoti, MongoDB sostituirà il valore di timestamp vuoto con il valore di timestamp corrente. L'eccezione a questo è se il _id il campo contiene un timestamp vuoto. Il valore del timestamp verrà sempre inserito così com'è e non sostituito.

Inserimento di un nuovo Timestamp valore in MongoDB utilizzerà il new Timestamp() funzione e assomiglia a questo:

db.mytestcoll.insertOne( {ts: new Timestamp() });{        "acknowledged": true,        "insertedId": ObjectId("614b37296a124db40ae74d23")}

Quando esegui una query sulla raccolta, restituirai un risultato simile a:

db.mytestcoll.find().pretty(){        "_id" : ObjectId("614b37296a124db40ae74d24"),         "ts" : Timestamp( { t: 1412180887, i: 1 })}


Oggetto

L'Object il tipo di dati in MongoDB viene utilizzato per archiviare i documenti incorporati. Un documento incorporato è una serie di documenti nidificati in key: value formato coppia. Dimostriamo l'Object digita sotto:

var classGrades = {"Physics": 88, "German": 92, "LitTheoery": 79}db.mytestcoll.insertOne({student_name: "John Smith", report_card: classGrades}){        "acknowledged": true,        "insertedId": ObjectId("614b37296a124db40ae74d18")}

Possiamo quindi visualizzare il nostro nuovo documento:

db.mytestcoll.find().pretty(){    _id: ObjectId("614b37296a124db40ae74d18"),    student_name: 'John Smith',    report_card: {Physics: 88, German: 92, LitTheoery: 79}}

L'Object il tipo di dati ottimizza per la memorizzazione dei dati a cui è possibile accedere al meglio insieme. Fornisce alcune efficienze in termini di archiviazione, velocità e durata invece di memorizzare separatamente ogni segno di classe, dall'esempio sopra.



Dati binari

I Binary data o BinData , il tipo di dati fa esattamente ciò che implica il suo nome e memorizza i dati binari per il valore di un campo. BinData viene utilizzato al meglio durante l'archiviazione e la ricerca di dati, grazie alla sua efficienza nella rappresentazione di array di bit. Questo tipo di dati può essere rappresentato nei seguenti modi:

        Type         | Number |     Alias    |  ------------------ | ------ | ------------ |      Binary data    |    5   |   "binData"  |

Ecco un esempio di aggiunta di alcuni Binary data in un documento in una raccolta:

var data = BinData(1, "111010110111100110100010101")db.mytestcoll.insertOne({binaryData: data}){        "acknowledged": true,        "insertedId": ObjectId("614b37296a124db40ae74d20")}

Per poi vedere il documento risultante:

db.mytestcoll.find().pretty(){        "_id" : ObjectId("614b37296a124db40ae74d20"),        "binaryData" : BinData(1, "111010110111100110100010101")}


ObjectId

Il ObjectId type è specifico di MongoDB e memorizza l'ID univoco del documento. MongoDB fornisce un _id campo per ogni documento. ObjectId ha una dimensione di 12 byte e può essere rappresentato come segue:

        Type         | Number |     Alias    |  ------------------ | ------ | ------------ |      ObjectId       |    7   |   "objectId" |

ObjectId è costituito da tre parti che compongono la sua struttura a 12 byte:

  • un valore timestamp a 4 byte , che rappresenta la creazione dell'ObjectId, misurata in secondi dall'epoca di Unix
  • un valore casuale a 5 byte
  • un contatore incrementale a 3 byte inizializzato su un valore casuale

In MongoDB, ogni documento all'interno di una raccolta richiede un _id univoco agire come chiave primaria. Se il _id campo viene lasciato vuoto per un documento inserito, MongoDB genererà automaticamente un ObjectId per il campo.

Ci sono diversi vantaggi nell'usare ObjectIds per _id :

  • in mongosh (shell MongoDB), l'ora di creazione di ObjectId è accessibile utilizzando ObjectId.getTimestamp() metodo.
  • ordinamento su un _id campo che memorizza ObjectId tipi di dati è un equivalente vicino all'ordinamento per ora di creazione.

Finora abbiamo visto ObjectIds in tutti gli esempi e saranno simili a questo:

db.mytestcoll.find().pretty(){         _id: ObjectId("614b37296a124db40ae74d19")}

Nota :i valori ObjectId dovrebbero aumentare nel tempo, tuttavia non sono necessariamente monotoni. Questo perché loro:

  • Contengono solo un secondo di risoluzione temporale, quindi i valori creati nello stesso secondo non hanno un ordinamento garantito
  • I valori sono generati dai client, che possono avere clock di sistema diversi


Booleano

MongoDB ha il Boolean nativo tipo di dati per la memorizzazione di valori true e false all'interno di una raccolta. Boolean in MongoDB può essere rappresentato come segue:

        Type         | Number |     Alias    |  ------------------ | ------ | ------------ |       Boolean       |    8   |     "bool"   |

Inserimento di un documento con un Boolean il tipo di dati sarà simile al seguente:

db.mytestcoll.insertOne({isCorrect: true, isIncorrect: false}){        "acknowledged": true,        "insertedId": ObjectId("614b37296a124db40ae74d21")}

Quindi durante la ricerca del documento il risultato apparirà come:

db.mytestcoll.find().pretty(){    "_id" : ObjectId("614b37296a124db40ae74d21")    "isCorrect" : true,    "isIncorrect" : false}


Espressione regolare

L'Regular Expression il tipo di dati in MongoDB consente la memorizzazione di espressioni regolari come valore di un campo. MongoDB usa PCRE (Perl Compatible Regular Expression) come linguaggio di espressioni regolari.

Può essere rappresentato nel modo seguente:

        Type         | Number |  Alias  |  ------------------ | ------ | ------- |  Regular Expression |   11   | "regex" |

BSON consente di evitare il tipico passaggio di "conversione da stringa" che si verifica comunemente quando si lavora con espressioni regolari e database. Questo tipo sarà molto utile quando si scrivono oggetti di database che richiedono modelli di convalida o trigger di corrispondenza.

Ad esempio, puoi inserire l'Regular Expression tipo di dati come questo:

db.mytestcoll.insertOne({exampleregex: /tt/}){        "acknowledged": true,        "insertedId": ObjectId("614b37296a124db40ae74d16")}db.mytestcoll.insertOne({exampleregext:/t+/}){        "acknowledged": true,        "insertedId": ObjectId("614b37296a124db40ae74d17")}

Questa sequenza di dichiarazioni aggiungerà questi documenti alla tua collezione. Puoi quindi interrogare la tua collezione per trovare i documenti inseriti:

db.mytestcoll.find().pretty(){        _id: ObjectId("614b37296a124db40ae74d16"), exampleregex: /tt/,        _id: ObjectId("614b37296a124db40ae74d17"), exampleregex: /t+/ }

I modelli di espressione regolare vengono archiviati come regex e non come stringhe. Ciò ti consente di eseguire query per una determinata stringa e ottenere documenti restituiti con un'espressione regolare corrispondente alla stringa desiderata.



JavaScript (senza ambito)

Proprio come la menzionata Regular Expression tipo di dati, BSON consente a MongoDB di archiviare funzioni JavaScript senza ambito come proprio tipo. Il JavaScript tipo può essere riconosciuto come segue:

        Type         | Number |     Alias    |  ------------------ | ------ | ------------ |      JavaScript     |   13   | "javascript" |

Aggiunta di un documento alla tua raccolta con JavaScript il tipo di dati sarà simile a questo:

db.mytestcoll.insertOne({jsCode: "function(){var x; x=1}"}){        "acknowledged": true,        "insertedId": ObjectId("614b37296a124db40ae74d122")}

Questa funzionalità ti consente di memorizzare le funzioni JavaScript all'interno delle tue raccolte MongoDB, se necessario per un caso d'uso particolare.

Nota :Con MongoDB versione 4.4 e successive, un tipo JavaScript alternativo, il JavaScript with Scope tipo di dati, è stato deprecato



Conclusione

In questo articolo, abbiamo trattato la maggior parte dei tipi di dati comuni che sono utili quando si lavora con i database MongoDB. Esistono tipi aggiuntivi che non sono trattati in modo esplicito in questa guida che potrebbero essere utili a seconda del caso d'uso. Iniziare conoscendo questi tipi copre la maggior parte dei casi d'uso. È una solida base per iniziare a modellare il tuo database MongoDB.

È importante sapere quali tipi di dati sono disponibili quando si utilizza un database in modo da utilizzare valori validi e operare sui dati con risultati previsti. Ci sono dei rischi in cui potresti incorrere senza digitare correttamente i tuoi dati, come mostrato nel Double rispetto a Decimal128 esercizio. È importante pensarci prima di impegnarsi in un determinato tipo.

Se sei interessato a controllare Prisma con un database MongoDB, puoi consultare la documentazione del connettore dati.