迁移未定义数据和查询
从 MongoDB 8.0 开始,在相等匹配表达式中对null的比较不匹配undefined值。
例如,考虑以下文档和查询
// people collection [ { _id: 1, name: null }, { _id: 2, name: undefined }, { _id: 3, name: [ "Gabriel", undefined ], { _id: 4, names: [ "Alice", "Charu" ] } ]
db.people.find( { name: null } )
MongoDB 8.0 之前,前面的查询会匹配以下文档:
字段
name为null(_id: 1)字段
name为undefined或包含undefined数组元素(_id: 2和_id: 3)字段
name不存在(_id: 4)
从 MongoDB 8.0 开始,前面的查询不会匹配字段 name 为 undefined 或包含 undefined 数组元素的文档。查询仅匹配以下文档:
name字段为null或包含一个包含null数组元素的_id: 1字段
name不存在(_id: 4)
此查询行为变更也会影响以下操作
为了适应这一行为变更,你可以
注意
undefined是一个已弃用的BSON类型。MongoDB Shell和驱动程序的新版本在执行插入和更新操作时,会自动将undefined值转换为null。本页面的指导适用于包含来自旧版本驱动程序或旧版mongo Shell的undefined值的部署。
删除未定义字段
如果你不需要在文档中保留具有undefined值的字段,你可以删除这些字段。MongoDB灵活的数据模型意味着你的集合的文档字段不需要保持一致,因此你可以从文档的子集中删除特定的字段。
如何从你的文档中删除未定义的字段取决于你是否知道要删除的字段名。如果你知道字段名,则操作性能更高,因为它可以使用索引。
请参阅以下内容
删除已知名称的字段
如果你知道包含要删除的undefined值的字段名,可以使用以下示例。示例更新people集合以删除
如果其值是标量值
undefined,则name字段。name字段中的undefined数组元素。
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" } } } } ] )
运行操作后,people 集合包含以下文档
[ { _id: 1, name: null }, { _id: 2 }, { _id: 3, name: [ "Gabriel" ] } { _id: 4, names: [ "Alice", "Charu" ] } ]
删除具有未知名称的字段
如果您不知道哪些字段包含 undefined 值,请使用以下示例删除所有顶层 undefined 字段。
注意
当您未指定更新操作的字段名称时,该操作的性能不佳,因为查询无法使用索引。如果您在大型集合上运行以下示例,查询可能很慢且资源密集。
以下示例从 people 集合中删除值是 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" ] } } } } } } ] )
运行操作后,people 集合包含以下文档
[ { _id: 1, name: null }, { _id: 2 }, { _id: 3, name: [ "Gabriel", undefined ] } { _id: 4, names: [ "Alice", "Charu" ] } ]
注意
前面的方法仅修改顶层字段。具有 _id: 3 的文档仍然包含 undefined 值,因为该值出现在数组中。
将未定义值更新为 Null
您可以将 undefined 数据值更新为 null 数据类型。使用这种方法将数据迁移到已弃用的 undefined 数据类型,同时保留文档字段。
如何更新未定义字段取决于您是否知道要更新的字段名称。如果您知道字段名称,则操作性能更好,因为它可以使用索引。
请参阅以下内容
使用已知名称更新字段
如果您知道包含您想设置为 null 的 undefined 值的字段名称,请使用以下示例。以下示例更新 people 集合,将这些值设置为 null
如果其值是标量值
undefined,则name字段。undefined数组元素出现在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 } } } } ] )
运行操作后,people 集合包含以下文档
[ { _id: 1, name: null }, { _id: 2, name: null }, { _id: 3, name: [ "Gabriel", null ] } { _id: 4, names: [ "Alice", "Charu" ] } ]
使用未知名称更新字段
如果您不知道哪些字段包含 undefined 值,请使用以下示例将所有顶层 undefined 字段设置为 null。
注意
当您未指定更新操作的字段名称时,该操作的性能不佳,因为查询无法使用索引。如果您在大型集合上运行以下示例,查询可能很慢且资源密集。
以下示例更新 people 集合,将顶层文档字段中的 undefined 设置为 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" } } } } } } ] )
运行操作后,people 集合包含以下文档
[ { _id: 1, name: null }, { _id: 2, name: null }, { _id: 3, name: [ "Gabriel", undefined ] } { _id: 4, names: [ "Alice", "Charu" ] } ]
注意
前面的方法仅修改顶层字段。具有 _id: 3 的文档仍然包含 undefined 值,因为该值出现在数组中。
更新查询以匹配未定义值
如果您无法将数据类型从 null 迁移到 undefined,则可以重新编写查询以匹配未定义值。如果您采用这种方法,您的数据仍将包含已弃用的 undefined BSON 类型。
若要使对 null 的查询匹配未定义值,请添加一个显式匹配 undefined 类型的查询谓词。例如,以下查询匹配 name 为 undefined、null 或缺失的文档
db.people.find( { $or: [ { name: null }, { name: { $type: "undefined" } } ] } )
该查询返回 people 集合中的所有文档
[ { _id: 1, name: null }, { _id: 2, name: undefined }, { _id: 3, name: [ "Gabriel", undefined ], { _id: 4, names: [ "Alice", "Charu" ] } ]