Join us at MongoDB.local London on 7 May to unlock new possibilities for your data. Use WEB50 to save 50%.
Register now >
Docs Menu
Docs Home
/ /

Migrar los datos y query no definidos

A partir de MongoDB 8.0, las comparaciones con null en expresiones de coincidencia exacta no hacen coincidir valores undefined.

Por ejemplo, considera estos documentos y la query:

// create the people collection
db.people.insertMany( [
{ _id: 1, name: null },
{ _id: 2, name: undefined },
{ _id: 3, name: [ "Gabriel", undefined ] },
{ _id: 4, names: [ "Alice", "Charu" ] }
] )
db.people.find( { name: null } )

Antes de MongoDB 8.0, el query anterior coincidiría con documentos donde:

  • El campo name es null (_id: 1)

  • El campo name es undefined o contiene un elemento de arreglo undefined (_id: 2 y _id: 3)

  • El campo name no existe (_id: 4)

A partir de MongoDB 8.0, la query anterior no coincide con documentos en que el campo name es undefined o contiene undefined elementos de arreglo. La query solo coincide con documentos en que:

  • El campo name es null o contiene un elemento de arreglo null (_id: 1)

  • El campo name no existe (_id: 4)

Este cambio de comportamiento de query también afecta estas operaciones:

  • $eq

  • $in

  • $lookup, porque un campo local null ya no coincide con un campo foráneo undefined.

Para tener en cuenta este cambio de comportamiento, puedes:

  • Eliminar campos no definidos.

  • Actualizar valores no definidos a nulos.

  • Actualizar las consultas para que coincidan con valores indefinidos.

Nota

undefined es un tipo BSON obsoleto. Las versiones recientes de la MongoDB Shell y los drivers convierten automáticamente los valores de undefined a null al realizar inserciones y actualizaciones. La orientación en esta página se aplica a las implementaciones que tengan valores undefined de versiones antiguas de drivers o de la shell heredada mongo.

Si no necesita conservar campos con valores undefined en sus documentos, puede eliminarlos. El modelo de datos flexible de MongoDB implica que los campos de documentos de su colección no necesitan ser consistentes, por lo que puede eliminar un campo específico de un subconjunto de documentos.

La forma de remover campos indefinidos de sus documentos depende de si conoce el nombre del campo a remover. Si conoces el nombre del campo, la operación es más eficiente porque se puede usar un índice.

Consulta cualquiera de las siguientes opciones:

Si conoces el nombre del campo que contiene valores de undefined que deseas remover, utiliza el siguiente ejemplo. El ejemplo actualiza la colección people para remover:

  • El campo name si su valor es el valor escalar undefined.

  • undefined elementos de la matriz en el campo name.

db.people.updateMany(
{ name: { $type: "undefined" } },
[ {
$set: {
"name": {
$cond: {
// When "name" is an array, convert { name: [ "Alice", undefined ] }
// to { name: [ "Alice" ] }
if: {
$eq: [ { $type: "$name" }, "array" ]
},
then: {
$filter: {
input: "$name",
cond: {
$not: { $eq: [ { $type: "$$this" }, "undefined" ] }
}
},
},
// When "name" is scalar undefined, remove it
else: "$$REMOVE"
}
}
}
} ]
)

Después de ejecutar la operación, la colección people contiene estos documentos:

[
{ _id: 1, name: null },
{ _id: 2 },
{ _id: 3, name: [ "Gabriel" ] }
{ _id: 4, names: [ "Alice", "Charu" ] }
]

Si aún no sabes en qué campos hay valores undefined, usa el siguiente ejemplo para remover todos los campos a nivel superior undefined.

Nota

Cuando no especifiques un nombre de campo para el actualizar, la operación no será eficiente porque la query no podrá utilizar un índice. Si ejecuta el siguiente ejemplo en una colección grande, la query podría ser lenta y consumir muchos recursos.

El siguiente ejemplo remueve los campos de documentos de nivel superior de la colección people donde el valor es undefined:

db.people.updateMany(
{ },
[ {
$replaceWith: {
// Detect undefined top-level fields under the root and remove them
$arrayToObject: {
$filter: {
input: { $objectToArray: "$$ROOT" },
cond: {
$not: { $eq: [ { $type: "$$this.v" }, "undefined" ] }
}
}
}
}
} ]
)

Después de ejecutar la operación, la colección people contiene estos documentos:

[
{ _id: 1, name: null },
{ _id: 2 },
{ _id: 3, name: [ "Gabriel", undefined ] }
{ _id: 4, names: [ "Alice", "Charu" ] }
]

Nota

El enfoque anterior sólo modifica los campos de nivel superior. El documento con _id: 3 todavía contiene un valor undefined porque el valor aparece en un arreglo.

Puedes actualizar los valores de datos undefined al tipo de datos null. Usa este método para migrar tus datos desde el tipo de dato obsoleto undefined y conservar los campos de tus documentos.

La forma de actualizar los campos indefinidos depende de si conoces el nombre del campo que deseas actualizar. Si se conoce el nombre del campo, la operación es más eficiente porque puede utilizar un índice.

Consulta cualquiera de las siguientes opciones:

Si conoces el nombre del campo que contiene valores de undefined que deseas establecer en null, utiliza el siguiente ejemplo. El ejemplo actualiza la colección de people para establecer los siguientes valores a null:

  • El campo name si su valor es el valor escalar undefined.

  • undefined elementos del arreglo que aparecen en el campo name.

db.people.updateMany(
{ name: { $type: "undefined" } },
[ {
$set: {
"name": {
$cond: {
// When "name" is an array, convert { name: [ "Alice", undefined ] }
// to { name: [ "Alice", null ] }
if: {
$eq: [ { $type: "$name" }, "array" ]
},
then: {
$map: {
input: "$name",
in: {
$cond: {
if: { $eq: [ { $type: "$$this" }, "undefined" ] },
then: null,
else: "$$this"
}
}
},
},
// When "name" is the scalar undefined, convert to null
else: null
}
}
}
} ]
)

Después de ejecutar la operación, la colección people contiene estos documentos:

[
{ _id: 1, name: null },
{ _id: 2, name: null },
{ _id: 3, name: [ "Gabriel", null ] }
{ _id: 4, names: [ "Alice", "Charu" ] }
]

Si no sabe qué campos contienen valores undefined, utilice el siguiente ejemplo para establecer todos los campos de nivel superior undefined en null.

Nota

Cuando no especifiques un nombre de campo para el actualizar, la operación no será eficiente porque la query no podrá utilizar un índice. Si ejecuta el siguiente ejemplo en una colección grande, la query podría ser lenta y consumir muchos recursos.

El siguiente ejemplo actualiza la colección people para establecer los campos de documento de nivel superior undefined a null:

db.people.updateMany(
{ },
[ {
$replaceWith: {
// Detect undefined top-level fields under the root and replace them with null
$arrayToObject: {
$map: {
input: { $objectToArray: "$$ROOT" },
in: {
$cond: {
if: { $eq: [ { $type: "$$this.v" }, "undefined" ] },
then: { k: "$$this.k", v: null },
else: "$$this"
}
}
}
}
}
} ]
)

Después de ejecutar la operación, la colección people contiene estos documentos:

[
{ _id: 1, name: null },
{ _id: 2, name: null },
{ _id: 3, name: [ "Gabriel", undefined ] }
{ _id: 4, names: [ "Alice", "Charu" ] }
]

Nota

El enfoque anterior sólo modifica los campos de nivel superior. El documento con _id: 3 todavía contiene un valor undefined porque el valor aparece en un arreglo.

Si no puedes migrar tus tipos de datos de null a undefined, puedes reescribir tus consultas para que coincidan con valores indefinidos. Si utiliza este método, sus datos seguirán conteniendo el tipo BSON undefined obsoleto.

Para que las queries para null coincidan con valores indefinidos, añade un predicado de query que coincida explícitamente con el tipo undefined. Por ejemplo, la siguiente query encuentra documentos donde name es undefined, null o está ausente:

db.people.find( {
$or: [
{ name: null },
{ name: { $type: "undefined" } }
]
} )

La query devuelve todos los documentos de la colección people:

[
{ _id: 1, name: null },
{ _id: 2, name: undefined },
{ _id: 3, name: [ "Gabriel", undefined ],
{ _id: 4, names: [ "Alice", "Charu" ] }
]

Volver

Comparación y orden de clasificación

En esta página