迁移未定义的数据和查询
从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
集合以删除:
name
字段,如果其值为标量值undefined
。undefined
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" } } } } ] )
运行该操作后,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
:
name
字段,如果其值为标量值undefined
。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" ] } ]