sql >> Base de Datos >  >> NoSQL >> MongoDB

Introducción a los tipos de datos de MongoDB


Introducción

Al usar MongoDB, tiene la capacidad de ser flexible con la estructura de sus datos. No está obligado a mantener un cierto esquema en el que deben encajar todos sus documentos. Para cualquier campo dado en un documento, puede usar cualquiera de los tipos de datos disponibles soportado por MongoDB. A pesar de esta forma predeterminada de trabajar, puede imponer un esquema JSON en MongoDB para agregar validación en sus colecciones si lo desea. No entraremos en los detalles del diseño del esquema en esta guía, pero puede tener un efecto en la tipificación de datos si se implementa.

Los tipos de datos especifican un patrón general para los datos que aceptan y almacenan. Es fundamental comprender cuándo elegir un determinado tipo de datos sobre otro al planificar su base de datos. El tipo elegido dictará cómo puede operar con sus datos y cómo se almacenan.



JSON y BSON

Antes de entrar en los detalles de tipos de datos específicos, es importante comprender cómo MongoDB almacena los datos. MongoDB y muchas otras bases de datos NoSQL basadas en documentos utilizan JSON (notación de objetos de JavaScript) para representar registros de datos como documentos.

Hay muchas ventajas en el uso de JSON para almacenar datos. Algunos de ellos son:

  • facilidad de lectura, aprendizaje y familiaridad entre los desarrolladores
  • flexibilidad en el formato, ya sea escaso, jerárquico o profundamente anidado
  • autodescriptivo, que permite que las aplicaciones operen fácilmente con datos JSON
  • permite centrarse en un número mínimo de tipos básicos

JSON admite todos los tipos de datos básicos como cadena, número, booleano, etc. MongoDB en realidad almacena registros de datos como documentos JSON (BSON) con codificación binaria. Al igual que JSON, BSON admite la incorporación de documentos y matrices dentro de otros documentos y matrices. BSON permite tipos de datos adicionales que no están disponibles para JSON.



¿Cuáles son los tipos de datos en MongoDB?

Antes de entrar en detalles, echemos un vistazo general a los tipos de datos compatibles con MongoDB.

MongoDB admite una variedad de tipos de datos adecuados para varios tipos de datos simples y complejos. Estos incluyen:

Texto

  • String

Numérico

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

Fecha/Hora

  • Date
  • Timestamp

Otro

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

En MongoDB, cada tipo de BSON tiene identificadores de cadena y enteros. Cubriremos los más comunes con más profundidad a lo largo de esta guía.



Tipos de cadena

El tipo de cadena es el tipo de datos MongoDB más utilizado. Cualquier valor escrito entre comillas dobles "" en JSON es un valor de cadena. Cualquier valor que desee almacenar como texto se escribirá mejor como String . Las cadenas BSON son UTF-8 y se representan en MongoDB como:

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

Generalmente, los controladores para lenguajes de programación se convertirán del formato de cadena del lenguaje a UTF-8 al serializar y deserializar BSON. Esto hace que BSON sea un método atractivo para almacenar caracteres internacionales con facilidad, por ejemplo.

Insertar un documento con una String el tipo de datos se verá así:

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

Consultar la colección devolverá lo siguiente:

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

Usando el $type operador

Antes de pasar al siguiente tipo de datos, es importante saber cómo puede escribir el valor antes de realizar inserciones. Usaremos el ejemplo anterior para demostrar el uso del $type operador en MongoDB.

Digamos que ha pasado un tiempo desde que trabajamos con mytestcoll colección de antes. Queremos insertar algunos documentos adicionales en la colección con el first_name campo. Para verificar que usamos String como el tipo de datos almacenado como un valor de first_name originalmente, podemos ejecutar lo siguiente usando el alias o el valor numérico del tipo de datos:

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

O

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

Ambas consultas devuelven una salida de todos los documentos que tienen una String valor almacenado para first_name de la inserción de nuestra sección anterior:

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

Si consulta un tipo que no está almacenado en el first_name campo de cualquier documento, no obtendrá ningún resultado. Esto indica que es otro tipo de datos almacenado en first_name .

También puede consultar varios tipos de datos a la vez con $type operador como el siguiente:

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

Porque no insertamos ningún Null escriba valores en nuestra colección, el resultado será el mismo:

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

Puede usar el mismo método con todos los siguientes tipos que discutiremos.




Números y valores numéricos

MongoDB incluye una gama de tipos de datos numéricos adecuados para diferentes escenarios. Decidir qué tipo usar depende de la naturaleza de los valores que planea almacenar y sus casos de uso para los datos. JSON llama a cualquier cosa con números un Número . Eso obliga al sistema a descubrir cómo convertirlo en el tipo de datos nativo más cercano. Comenzaremos explorando los números enteros y cómo funcionan en MongoDB.


Entero

El Integer El tipo de datos se utiliza para almacenar números como números enteros sin fracciones ni decimales. Los números enteros pueden ser valores positivos o negativos. Hay dos tipos en MongoDB, 32-Bit Integer y 64-Bit Integer . Se pueden representar de las dos formas que se muestran en la siguiente tabla, number y alias :

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

Los rangos en los que puede caber un valor para cada tipo son los siguientes:

  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

Los tipos anteriores están limitados por su rango válido. Cualquier valor fuera del rango resultará en un error. Insertar un Integer escriba en MongoDB se verá como a continuación:

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

Y encontrar el resultado devolverá lo siguiente:

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

Como sugieren los nombres, un 32-Bit Integer tiene 32 bits de precisión de enteros, lo cual es útil para valores enteros más pequeños que no desea almacenar como una secuencia de dígitos. Cuando aumenta el tamaño del número, puede subir al 64-Bit Integer que tiene 64 bits de precisión de enteros y se ajusta al mismo caso de uso que el anterior.



Doble

En BSON, el reemplazo predeterminado para el Número de JSON es el Double tipo de datos. El Double El tipo de datos se usa para almacenar un valor de coma flotante y se puede representar en MongoDB de la siguiente manera:

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

Los números de coma flotante son otra forma de expresar números decimales, pero sin una precisión exacta y constante.

Los números de punto flotante pueden funcionar con una gran cantidad de decimales de manera eficiente pero no siempre exacta. El siguiente es un ejemplo de ingreso de un documento con el Double escribe en tu colección:

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

Puede haber ligeras diferencias entre la entrada y la salida al calcular con dobles que podrían conducir a un comportamiento inesperado. Al realizar operaciones que requieren valores exactos, MongoDB tiene un tipo más preciso.



Decimal128

Si está trabajando con números muy grandes con mucho rango de punto flotante, entonces Decimal128 El tipo de datos BSON será la mejor opción. Este será el tipo más útil para valores que requieren mucha precisión, como en casos de uso que involucran operaciones monetarias exactas. El Decimal128 el tipo se representa como:

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

El tipo BSON, Decimal128 , proporciona 128 bits de representación decimal para almacenar números donde el redondeo exacto de decimales es importante. Decimal128 admite 34 dígitos decimales de precisión, o un sinificando con un rango de -6143 a +6144. Esto permite una gran cantidad de precisión.

Insertar un valor usando el Decimal128 el tipo de datos requiere el uso de NumberDecimal() constructor con tu número como String para evitar que MongoDB use el tipo numérico predeterminado, Double .

Aquí, demostramos esto:

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

Al consultar la colección, obtienes el siguiente resultado:

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

El valor numérico mantiene su precisión permitiendo operaciones exactas. Para demostrar el Decimal128 tipo versus el Double , podemos realizar el siguiente ejercicio.



Cómo se puede perder la precisión según el tipo de datos

Digamos que queremos insertar un número con muchos valores decimales como Double en MongoDB con lo siguiente:

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

Cuando consultamos estos datos, obtenemos el siguiente resultado:

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

Este valor se redondea a 9999999.5 , perdiendo su valor exacto con el que lo ingresamos. Esto hace que Double inadecuado para el almacenamiento de números con muchos decimales.

El siguiente ejemplo demuestra dónde se perderá la precisión al pasar un Double implícitamente con Decimal128 en lugar de una String como en el ejemplo anterior.

Empezamos insertando el siguiente Double de nuevo pero con NumberDecimal() para que sea un Decimal128 tipo:

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

Nota :Al realizar esta inserción en el shell de MongoDB, se muestra el siguiente mensaje de advertencia:

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

Este mensaje de advertencia indica que el número que está tratando de pasar podría estar sujeto a una pérdida de precisión. Sugieren usar una String usando NumberDecimal() para que no pierdas precisión.

Si ignoramos la advertencia e insertamos el documento de todos modos, la pérdida de precisión se ve en los resultados de la consulta debido al redondeo del valor:

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

Si seguimos el NumberDecimal() recomendado enfoque usando un String veremos los siguientes resultados con precisión mantenida:

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

Para cualquier caso de uso que requiera valores precisos y exactos, esta devolución podría causar problemas. Cualquier trabajo que involucre operaciones monetarias es un ejemplo donde la precisión será extremadamente importante y tener valores exactos es fundamental para cálculos precisos. Esta demostración destaca la importancia de saber qué tipo de datos numéricos será el más adecuado para sus datos.




Fecha

El BSON Date El tipo de datos es un número entero de 64 bits que representa el número de milisegundos desde la época de Unix (1 de enero de 1970). Este tipo de datos almacena la fecha o la hora actual y se puede devolver como un objeto de fecha o como una cadena. Date se representa en MongoDB de la siguiente manera:

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

Nota :BSON Date el tipo está firmado. Los valores negativos representan fechas anteriores a 1970.

Hay tres métodos para devolver valores de fecha.

  1. Date() - devuelve una cadena

  2. new Date() - devuelve un objeto de fecha usando ISODate() envoltorio

  3. ISODate() - también devuelve un objeto de fecha usando ISODate() envoltorio

Demostramos estas opciones a continuación:

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

Y al volver:

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

También está el Timestamp tipo de datos en MongoDB para representar el tiempo. Sin embargo, Timestamp va a ser más útil para uso interno y no lo es asociado con la Date tipo. El tipo en sí es una secuencia de caracteres que se utiliza para describir la fecha y hora en que ocurre un evento. Timestamp es un valor de 64 bits donde:

  • los 32 bits más significativos son time_t valor (segundos desde la época de Unix)
  • los 32 bits menos significativos son un ordinal incremental para operaciones dentro de un segundo determinado

Su representación en MongoDB será la siguiente:

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

Al insertar un documento que contiene campos de nivel superior con marcas de tiempo vacías, MongoDB reemplazará el valor de marca de tiempo vacío con el valor de marca de tiempo actual. La excepción a esto es si el _id El campo contiene una marca de tiempo vacía. El valor de la marca de tiempo siempre se insertará tal cual y no se reemplazará.

Insertar una nueva Timestamp el valor en MongoDB usará el new Timestamp() función y se ve algo como esto:

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

Al consultar la colección, devolverá un resultado parecido a:

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


Objeto

El Object El tipo de datos en MongoDB se utiliza para almacenar documentos incrustados. Un documento incrustado es una serie de documentos anidados en key: value formato de pareja. Demostramos el Object escriba a continuación:

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

Entonces podemos ver nuestro nuevo documento:

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

El Object el tipo de datos se optimiza para almacenar datos a los que se accede mejor juntos. Proporciona algunas eficiencias en cuanto al almacenamiento, la velocidad y la durabilidad en lugar de almacenar cada marca de clase, del ejemplo anterior, por separado.



Datos binarios

Los Binary data o BinData , el tipo de datos hace exactamente lo que su nombre implica y almacena datos binarios para el valor de un campo. BinData se usa mejor cuando almacena y busca datos, debido a su eficiencia en la representación de matrices de bits. Este tipo de datos se puede representar de las siguientes maneras:

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

Aquí hay un ejemplo de cómo agregar algunos Binary data en un documento en una colección:

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

Para luego ver el documento resultante:

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


ObjectId

El ObjectId El tipo es específico de MongoDB y almacena la identificación única del documento. MongoDB proporciona un _id campo para cada documento. ObjectId tiene un tamaño de 12 bytes y se puede representar de la siguiente manera:

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

ObjectId consta de tres partes que componen su composición de 12 bytes:

  • un valor de marca de tiempo de 4 bytes , que representa la creación de ObjectId, medida en segundos desde la época de Unix
  • un valor aleatorio de 5 bytes
  • un contador incremental de 3 bytes inicializado a un valor aleatorio

En MongoDB, cada documento dentro de una colección requiere un _id único para actuar como una clave principal. Si el _id el campo se deja vacío para un documento insertado, MongoDB generará automáticamente un ObjectId para el campo.

Hay varios beneficios al usar ObjectIds para el _id :

  • en mongosh (Shell de MongoDB), la hora de creación del ObjectId es accesible mediante ObjectId.getTimestamp() método.
  • ordenando en un _id campo que almacena ObjectId tipos de datos es un equivalente cercano a ordenar por tiempo de creación.

Hemos visto ObjectIds a lo largo de los ejemplos hasta ahora, y se verán similares a esto:

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

Nota :Los valores de ObjectId deberían aumentar con el tiempo, sin embargo, no son necesariamente monótonos. Esto se debe a que:

  • Solo contiene un segundo de resolución temporal, por lo que los valores creados en el mismo segundo no tienen un orden garantizado
  • los valores son generados por los clientes, que pueden tener diferentes relojes del sistema


Booleano

MongoDB tiene el Boolean nativo tipo de datos para almacenar valores verdaderos y falsos dentro de una colección. Boolean en MongoDB se puede representar de la siguiente manera:

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

Insertar un documento con un Boolean el tipo de datos se parecerá a lo siguiente:

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

Luego, al buscar el documento, el resultado aparecerá como:

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


Expresión Regular

La Regular Expression tipo de datos en MongoDB permite el almacenamiento de expresiones regulares como el valor de un campo. MongoDB utiliza PCRE (expresión regular compatible con Perl) como lenguaje de expresión regular.

Se puede representar de la siguiente manera:

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

BSON le permite evitar el paso típico de "convertir desde cadena" que se experimenta comúnmente cuando se trabaja con expresiones regulares y bases de datos. Este tipo será más útil cuando escriba objetos de base de datos que requieran patrones de validación o disparadores coincidentes.

Por ejemplo, puede insertar la Regular Expression tipo de datos como este:

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

Esta secuencia de declaraciones agregará estos documentos a su colección. Luego puede consultar su colección para encontrar los documentos insertados:

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

Los patrones de expresiones regulares se almacenan como expresiones regulares y no como cadenas. Esto le permite consultar una cadena en particular y obtener documentos devueltos que tengan una expresión regular que coincida con la cadena deseada.



JavaScript (sin ámbito)

Al igual que la Regular Expression mencionada anteriormente tipo de datos, BSON permite que MongoDB almacene funciones de JavaScript sin alcance como su propio tipo. El JavaScript El tipo se puede reconocer de la siguiente manera:

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

Agregar un documento a su colección con JavaScript el tipo de datos se verá así:

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

Esta funcionalidad le permite almacenar funciones de JavaScript dentro de sus colecciones MongoDB si es necesario para un caso de uso particular.

Nota :Con MongoDB versión 4.4 y superior, un tipo de JavaScript alternativo, el JavaScript with Scope tipo de datos, ha quedado en desuso



Conclusión

En este artículo, cubrimos la mayoría de los tipos de datos comunes que son útiles cuando se trabaja con bases de datos MongoDB. Hay tipos adicionales que no se tratan explícitamente en esta guía que pueden ser útiles según el caso de uso. Comenzar conociendo estos tipos cubre la mayoría de los casos de uso. Es una base sólida para comenzar a modelar su base de datos MongoDB.

Es importante saber qué tipos de datos están disponibles cuando usa una base de datos para que esté usando valores válidos y operando en los datos con los resultados esperados. Hay riesgos con los que puede correr sin escribir correctamente sus datos como se muestra en el Double contra Decimal128 ejercicio. Es importante pensar en esto antes de comprometerse con cualquier tipo determinado.

Si está interesado en consultar Prisma con una base de datos MongoDB, puede consultar la documentación del conector de datos.