Docs 菜单
Docs 主页
/
MongoDB Manual
/ /

迁移未定义的数据和查询

在此页面上

  • 删除未定义的字段
  • 删除已知名称的字段
  • 删除具有未知名称的字段
  • 将未定义的值更新为 Null
  • 使用已知名称更新字段
  • 更新具有未知名称的字段
  • 更新查询以匹配未定义的值
  • 了解详情

从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 )

此查询行为更改还会影响以下操作:

  • $eq

  • $in

  • $lookup ,因为null本地字段不再与undefined外部字段匹配。

要考虑此行为更改,您可以:

  • 删除未定义的字段。

  • 将未定义的值更新为 Null。

  • 更新查询以匹配未定义的值。

注意

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 值,因为该值出现在大量中。

您可以将 undefined 数据值更新为 null数据类型。使用此方法可迁移数据从已弃用的 undefined数据类型迁移,同时保留文档字段。

如何更新未定义的字段取决于您是否知道要更新的字段名称。如果知道字段名称,则操作性能更高,因为它可以使用索引。

请参阅以下任一项:

如果您知道包含要设立为 nullundefined 值的字段的名称,请使用以下示例。该示例更新 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 类型显式匹配的查询谓词。示例,以下查询匹配 nameundefinednull 或缺失的文档:

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" ] }
]

后退

比较和排序顺序