Overview
MongoDB 5.0 mejora la compatibilidad con nombres de campo con el prefijo dólar ($) o puntos (.). Se han actualizado las reglas de validación para el almacenamiento de datos para facilitar el trabajo con fuentes de datos que utilizan estos caracteres. Sin embargo, se desaconseja su uso en nombres de campo, ya que MongoDB no admite algunas funciones de estos campos.
En la mayoría de los casos, los datos almacenados con nombres de campo como estos no son directamente accesibles. Es necesario usar métodos auxiliares como
$getField$setField, y en consultas que acceden a esos $literal campos.
Las reglas de validación del nombre del campo no son las mismas para todos los tipos de operaciones de almacenamiento. Esta página resume cómo las diferentes operaciones de inserción y actualización manejan los nombres de campo con el prefijo dólar ($).
Operaciones de inserción
Se permiten campos con prefijo dólar ($) como nombres de campos anidados y de nivel superior para inserciones.
db.sales.insertOne( { "$price": 50.00, "quantity": 30 } )
Se permiten campos con prefijo de dólar () en inserciones que utilizan palabras reservadas.$ $inc Se pueden usar nombres de operadores como como nombres de campo, así como palabras id como, db refy.
db.books.insertOne( { "$id": "h1961-01", "location": { "$db": "novels", "$ref": "2007042768", "$inc": true } } )
Una actualización que crea un nuevo documento durante una inserción y actualización se trata como un insert en lugar de un update para la validación del nombre de campo. Las$inserciones y actualizaciones pueden aceptar campos con el prefijo dólar (). Sin embargo, las inserciones y actualizaciones son un caso especial, y operaciones de actualización similares pueden causar un error si la match parte de la actualización selecciona un documento existente.
Este ejemplo de código tiene upsert: true, por lo que insertará un nuevo documento si la colección no contiene ya un documento que coincida con el término de consulta { "date": "2021-07-07" }. Si este ejemplo coincide con un documento existente, la actualización fallará, ya que $hotel tiene el prefijo dólar ($).
db.expenses.updateOne( { "date": "2021-07-07" }, { $set: { "phone": 25.17, "$hotel": 320.10 } }, { upsert: true } )
Actualizaciones de reemplazo de documentos
Los operadores de actualización reemplazan los campos existentes con nuevos documentos o los modifican. En los casos en que la actualización realiza un reemplazo, los campos con el prefijo dólar ($) no se permiten como nombres de campo de nivel superior.
Considere un documento como
{ "_id": "E123", "address": { "$number": 123, "$street": "Elm Road" }, "$rooms": { "br": 2, "bath": 1 } }
Podría utilizar un operador de actualización que reemplace un documento existente para modificar el campo address.$street, pero no podría actualizar el campo $rooms de esa manera.
db.housing.updateOne( { "_id": "E123" }, { $set: { "address.$street": "Elm Ave" } } )
Utiliza $setField como parte de una pipeline de agregación para actualizar de nivel superior campos con prefijo de dólar ($) como $rooms.
Actualizaciones que modifican documentos
Cuando una actualización modifica, en lugar de reemplazar, los campos de un documento existente, los campos con el prefijo dólar ($) pueden ser nombres de campo de nivel superior. Se puede acceder directamente a los subcampos, pero se necesita un método auxiliar para acceder a los campos de nivel superior.
Consideremos una colección con documentos como este registro de inventario:
{ _id: ObjectId("610023ad7d58ecda39b8d161"), "part": "AB305", "$bin": 200, "quantity": 100, "pricing": { sale: true, "$discount": 60 } }
El subcampo pricing.$discount puede consultarse directamente.
db.inventory.findAndModify( { query: { "part": { $eq: "AB305" } }, update: { $inc: { "pricing.$discount": 10 } } } )
Utilice $getField y para acceder al valor $literal del $bin campo de nivel superior.
db.inventory.findAndModify( { query: { $expr: { $eq: [ { $getField: { $literal: "$bin" } }, 200 ] } }, update: { $inc: { "quantity": 10 } } } )
Actualizaciones mediante pipelines de agregación
$setFieldUtilice, $getField y $literal en la etapa para $replaceWith modificar$ los campos con prefijo en dólares () en una secuencia de agregación.
Considere una colección de registros escolares como:
{ "_id": 100001, "$term": "fall", "registered": true, "grade": 4 }
Cree una nueva colección para el semestre de primavera utilizando una canalización para actualizar el campo con$ prefijo $term dólar ().
db.school.aggregate( [ { $match: { "registered": true } }, { $replaceWith: { $setField: { field: { $literal: "$term" }, input: "$$ROOT", value: "spring" } } }, { $out: "spring2022" } ] )
Evite nombres de campos ambiguos
No utilice un nombre de campo que sea igual a la notación de puntos para un campo incrustado. Si tiene un documento con un campo incrustado { "a" : { "b": ... } }, los demás documentos de esa colección no deben tener un campo de nivel superior "a.b".
Si puede referenciar un campo incrustado y un campo de nivel superior de la misma manera, las operaciones de indexación y fragmentación ocurren en el campo incrustado. No se puede indexar ni fragmentar en el campo de nivel superior "a.b" mientras la colección tiene un campo incrustado al que se hace referencia de la misma manera.
Por ejemplo, si su colección contiene documentos con un campo incrustado { "a" : { "b": ... } } y un campo de nivel superior "a.b", las operaciones de indexación y fragmentación ocurren en el campo incrustado. No es posible indexar o fragmentar en el campo de nivel superior "a.b" cuando su colección también contiene un campo incrustado { "a" : { "b": ... } }.
Restricciones generales
Además de las reglas de validación de almacenamiento mencionadas anteriormente, existen algunas restricciones generales sobre el uso de nombres de campo con prefijo dólar ($). Estos campos no pueden:
Estar indexado
Se utilizará como parte de una clave de fragmento
Ser validado usando
$jsonSchemaSe puede modificar con una secuencia de escape
Se utiliza con cifrado a nivel de campo
Se utilizará como subcampo en un documento
_id
Advertencia
Posible pérdida de datos con signos de dólar ($) y puntos (.)
Existe una pequeña posibilidad de pérdida de datos cuando se utilizan nombres de campo con el prefijo dólar ($) o nombres de campo que contienen puntos (.) si estos nombres de campo se utilizan junto con escrituras no reconocidas (nivel de confirmación de escritura w=0) en servidores que sean anteriores a MongoDB 5.0.
Al ejecutar los comandos insert, update y findAndModify, los controladores 5.0 compatibles con eliminan las restricciones sobre el uso de documentos con nombres de campo con el$ prefijo dólar () o puntos. (). Estos nombres de campo generaban un error en el cliente en versiones anteriores del controlador.
Las restricciones se eliminan independientemente de la versión del servidor a la que esté conectado el controlador. Si un controlador 5.0 envía un documento a un servidor más antiguo, el documento será rechazado sin enviar un error.
Advertencia
Preocupaciones de importación y exportación con signos de dólar ($) y puntos (.)
A partir de MongoDB 5.0, los nombres de los campos del documento pueden tener prefijo de dólar ($) y pueden contener puntos (.). Sin embargo, mongoimport y mongoexport pueden no funcionar como se espera en algunas situaciones con nombres de campos que utilizan estos caracteres.
MongoDB Extended JSON v2 no puede diferenciar entre los contenedores de tipo y los campos que tienen el mismo nombre que los contenedores de tipo. No utilices formatos JSON extendidos en contextos donde las representaciones BSON correspondientes puedan incluir claves con prefijo de dólar ($). El mecanismo DBRef es una excepción a esta regla general.
También hay restricciones en el uso de mongoimport y mongoexport con puntos (.) en los nombres de campo. Dado que los archivos CSV utilizan el punto (.) para representar jerarquías de datos, un punto (.) en el nombre de un campo se interpretará incorrectamente como un nivel de anidamiento.