迁移未定义的数据和查询
在此页面上
从 MongoDB 8.0开始,等值匹配表达式中与null
的比较与undefined
值不匹配。
示例,考虑以下文档和查询:
// 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 } )
在 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
)
此查询行为更改还会影响以下操作:
To account for this behavior change, you can:
注意
undefined
is a deprecated BSON type. Recent versions of the
MongoDB Shell and drivers automatically convert undefined
values
to null
when performing inserts and updates. The guidance on this
page applies to deployments that have undefined
values from older
driver versions or legacy mongo
shell.
Remove Undefined Fields
If you don't need to keep fields with undefined
values in your
documents, you can remove those fields. MongoDB's flexible data model
means your collection's document fields do not need to be consistent, so
you can remove a particular field from a subset of documents.
How to remove undefined fields from your documents depends on whether you know the field name to remove. If you know the field name, the operation is more performant because it can use an index.
See either:
Remove Field with Known Name
If you know the name of the field that contains undefined
values
that you want to remove, use the following example. The example updates
the people
collection to remove:
The
name
field if its value is the scalar valueundefined
.undefined
array elements in thename
field.
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" } } } } ] )
After you run the operation, the people
collection contains these
documents:
[ { _id: 1, name: null }, { _id: 2 }, { _id: 3, name: [ "Gabriel" ] } { _id: 4, names: [ "Alice", "Charu" ] } ]
Remove Fields with Unknown Names
If you don't know which fields contain undefined
values, use the
following example to remove all undefined
top-level fields.
注意
When you don't specify a field name for the update, the operation is not performant because the query can't use an index. If you run the following example on a large collection, the query might be slow and resource-intensive.
The following example removes top-level document fields from the
people
collection where the value is 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" ] } } } } } } ] )
After you run the operation, the people
collection contains these
documents:
[ { _id: 1, name: null }, { _id: 2 }, { _id: 3, name: [ "Gabriel", undefined ] } { _id: 4, names: [ "Alice", "Charu" ] } ]
注意
The preceding approach only modifies top-level fields. The document
with _id: 3
still contains an undefined
value because the
value appears in an array.
Update Undefined Values to Null
You can update undefined
data values to the null
data type. Use
this approach to migrate your data off of the deprecated undefined
data type while retaining your document fields.
How to update undefined fields depends on whether you know the field name to update. If you know the field name, the operation is more performant because it can use an index.
See either:
Update Field with Known Name
If you know the name of the field that contains undefined
values
that you want to set to null
, use the following example. The example
updates the people
collection to set the following values to
null
:
The
name
field if its value is the scalar valueundefined
.undefined
array elements that appear in thename
field.
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 } } } } ] )
After you run the operation, the people
collection contains these
documents:
[ { _id: 1, name: null }, { _id: 2, name: null }, { _id: 3, name: [ "Gabriel", null ] } { _id: 4, names: [ "Alice", "Charu" ] } ]
Update Fields with Unknown Names
If you don't know which fields contain undefined
values, use the
following example to set all undefined
top-level fields to null
.
注意
When you don't specify a field name for the update, the operation is not performant because the query can't use an index. If you run the following example on a large collection, the query might be slow and resource-intensive.
The following example updates the people
collection to set
undefined
top-level document fields to 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" } } } } } } ] )
After you run the operation, the people
collection contains these
documents:
[ { _id: 1, name: null }, { _id: 2, name: null }, { _id: 3, name: [ "Gabriel", undefined ] } { _id: 4, names: [ "Alice", "Charu" ] } ]
注意
The preceding approach only modifies top-level fields. The document
with _id: 3
still contains an undefined
value because the
value appears in an array.
Update Queries to Match Undefined Values
If you can't migrate your data types from null
to undefined
, you
can rewrite your queries to match undefined values. If you use this
approach, your data will still contain the deprecated undefined
BSON
type.
To have queries for null
match undefined values, add a query
predicate that explicitly matches the undefined
type. For example,
the following query matches documents where name
is undefined
,
null
, or missing:
db.people.find( { $or: [ { name: null }, { name: { $type: "undefined" } } ] } )
The query returns all documents in the people
collection:
[ { _id: 1, name: null }, { _id: 2, name: undefined }, { _id: 3, name: [ "Gabriel", undefined ], { _id: 4, names: [ "Alice", "Charu" ] } ]