文档菜单
文档首页
/
MongoDB 手册
/ / /

以美元符号开头的字段名

本页

  • 插入操作
  • 文档替换更新
  • 文档修改更新
  • 使用聚合管道的更新
  • 一般限制

本节总结了不同的插入和更新操作如何处理美元($)前缀的字段名。

以美元($)前缀的字段名允许用作插入操作中的顶层和嵌套字段名。

db.sales.insertOne( {
"$price": 50.00,
"quantity": 30
} )

以美元($)前缀的字段名允许在插入操作中使用其他保留字。例如,操作符名称$inc可以作为字段名,以及像iddbref这样的单词。

db.books.insertOne( {
"$id": "h1961-01",
"location": {
"$db": "novels",
"$ref": "2007042768",
"$inc": true
} } )

upsert操作期间创建新文档的更新被视为insert操作,而不是update操作,以验证字段名。Upserts可以接受美元($)前缀字段。然而,upserts是一个特殊情况,并且类似的更新操作如果更新操作的match部分选择了一个现有文档,可能会引发错误。

此代码示例具有upsert: true,因此如果集合中尚未包含与查询词匹配的文档,它将插入新文档,即{ "date": "2021-07-07" }。如果此示例代码匹配现有文档,则更新将失败,因为$hotel是美元($)前缀。

db.expenses.updateOne(
{ "date": "2021-07-07" },
{ $set: {
"phone": 25.17,
"$hotel": 320.10
} },
{ upsert: true }
)

更新运算符要么用新文档替换现有字段,要么修改这些字段。当更新执行替换操作时,不允许使用美元($)前缀的字段作为顶级字段名称。

考虑一个如下的文档:

{
"_id": "E123",
"address": {
"$number": 123,
"$street": "Elm Road"
},
"$rooms": {
"br": 2,
"bath": 1
}
}

您可以使用一个更新运算符替换现有文档以修改address.$street字段,但您不能以这种方式更新$rooms字段。

db.housing.updateOne(
{ "_id": "E123" },
{ $set: { "address.$street": "Elm Ave" } }
)

使用$setField作为聚合管道的一部分来更新顶级美元($)前缀字段,如$rooms

当更新修改而不是替换现有文档字段时,美元($)前缀字段可以是顶级字段名称。可以直接访问子字段,但需要辅助方法来访问顶级字段。

提示

另请参阅

考虑一个包含如下库存记录的集合:

{
_id: ObjectId("610023ad7d58ecda39b8d161"),
"part": "AB305",
"$bin": 200,
"quantity": 100,
"pricing": { sale: true, "$discount": 60 }
}

pricing.$discount子字段可以直接查询。

db.inventory.findAndModify( {
query: { "part": { $eq: "AB305" } },
update: { $inc: { "pricing.$discount": 10 } }
} )

使用$getField$literal来访问顶级$bin字段的值。

db.inventory.findAndModify( {
query: { $expr: {
$eq: [ { $getField: { $literal: "$bin" } }, 200 ]
} },
update: { $inc: { "quantity": 10 } }
} )

$replaceWith阶段使用$setField$getField$literal来修改聚合管道中美元符号($)前缀的字段。

考虑一个学校记录集合

{
"_id": 100001,
"$term": "fall",
"registered": true,
"grade": 4
}

使用一个管道创建一个新的春季学期集合,以更新美元符号($)前缀的$term字段。

db.school.aggregate( [
{ $match: { "registered": true } },
{ $replaceWith: {
$setField: {
field: { $literal: "$term" },
input: "$$ROOT",
value: "spring"
} } },
{ $out: "spring2022" }
] )

除了上述存储验证规则外,还有一些关于使用美元符号($)前缀的字段名的一般限制。这些字段不能

  • 被索引

  • 作为分片键的一部分使用

  • 使用$jsonSchema进行验证

  • 使用转义序列进行修改

  • 字段级加密一起使用

  • 作为_id文档的子字段使用

警告

使用美元符号($)和句点(.)可能导致数据丢失

当在旧于MongoDB 5.0的服务器上使用未确认写入(写关注 w=0)与美元符号($)前缀的字段名或包含句点(.)的字段名一起使用时,有可能导致数据丢失。

在执行 insertupdatefindAndModify 命令时,与 5.0 兼容的驱动程序移除了对使用字段名为美元符号($)前缀或包含点(.)的文档的限制。这些字段名在早期版本驱动程序中会生成客户端错误。

无论驱动程序连接到哪个服务器版本,都会移除这些限制。如果 5.0 驱动程序向旧服务器发送文档,该文档将被拒绝而不会发送错误。

警告

关于美元符号($)和点(.)的导入和导出注意事项

从 MongoDB 5.0 开始,文档字段名可以以美元符号($)开头,并且可以包含点(.)。然而,在 mongoimportmongoexport 中,某些情况下使用这些字符的字段名可能不会按预期工作。

MongoDB 扩展 JSON v2 无法区分类型包装器和偶然与类型包装器同名的数据字段。不要在可能包含美元符号($)前缀的相应 BSON 表示的上下文中使用扩展 JSON 格式。DBRef 机制是这一通用规则的一个例外。

在使用点(.)作为字段名字符的 mongoimportmongoexport 上也存在限制。由于 CSV 文件使用点(.)表示数据层次结构,字段名中的点(.)将被错误地解释为嵌套级别。

返回

周期和美元符号