Docs HomeMongoDB Manual

Field Names with Periods (.) and Dollar Signs ($)带句点(.)和美元符号($)的字段名

Overview概述

MongoDB 5.0 adds improved support for field names that are dollar ($) prefixed or that contain periods (.). MongoDB 5.0增加了对以美元($)为前缀或包含句点(.)的字段名的改进支持。The validation rules for storing data have been updated to make it easier to work with data sources that use these characters.存储数据的验证规则已经更新,以便更容易地使用使用这些字符的数据源。

In most cases data that has been stored using field names like these is not directly accessible. 在大多数情况下,使用类似字段名存储的数据是不可直接访问的。You need to use helper methods like $getField, $setField, and $literal in queries that access those fields.在访问这些字段的查询中,需要使用$getField$setField$literal等辅助方法。

The field name validation rules are not the same for all types of storage operations. 字段名称验证规则并非适用于所有类型的存储操作。This page summarizes how different insert and update operations handle dollar ($) prefixed field names.本页总结了不同的插入和更新操作如何处理以美元($)为前缀的字段名。

Insert operations插入操作

Dollar ($) prefixed fields are permitted as top level and nested field names for inserts.以美元($)为前缀的字段可以作为插入的顶级和嵌套字段名。

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

Dollar ($) prefixed fields are permitted on inserts using otherwise reserved words. 在使用其他保留字的插入中,允许使用美元($)前缀字段。Operator names like $inc can be used as field names as well as words like id, db, and ref.$inc这样的运算符名称既可以用作字段名称,也可以用作iddbref这样的单词。

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

An update which creates a new document during an upsert is treated as an insert rather than an update for field name validation. upsert期间创建新文档的update被视为insert,而不是字段名称验证的更新。Upserts can accept dollar ($) prefixed fields. upsert可以接受以美元($)为前缀的字段。However, upserts are a special case and similar update operations may cause an error if the match portion of the update selects an existing document.然而,upsert是一种特殊情况,如果更新的match部分选择了现有文档,类似的更新操作可能会导致错误。

This code sample has upsert: true so it will insert a new document if the collection doesn't already contain a document that matches the query term, { "date": "2021-07-07" }. 此代码示例具有upsert: true,因此如果集合中尚未包含与查询项{ "date": "2021-07-07" }匹配的文档,则它将插入一个新文档。If this sample code matches an existing document, the update will fail since $hotel is dollar ($) prefixed.如果此示例代码与现有文档匹配,则更新将失败,因为$hotel是以美元($)为前缀的。

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

Document Replacing Updates文档替换更新

Update operators either replace existing fields with new documents or else modify those fields. 更新运算符可以用新文档替换现有字段,也可以修改这些字段。In cases where the update performs a replacement, dollar ($) prefixed fields are not permitted as top level field names.在更新执行替换的情况下,不允许将以美元($)为前缀的字段作为顶级字段名。

Consider a document like考虑这样的文档

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

You could use an update operator that replaces an existing document to modify the address.$street field but you could not update the $rooms field that way.您可以使用替换现有文档的更新运算符来修改address.$street字段,但您无法以这种方式更新$rooms字段。

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

Use $setField as part of an aggregation pipeline to update top level dollar ($) prefixed fields like $rooms.使用$setField作为聚合管道的一部分,可以更新以美元($)为前缀的顶级字段,如$rooms

Document Modifying Updates文档修改更新

When an update modifies, rather than replaces, existing document fields, dollar ($) prefixed fields can be top level field names. 当更新修改而不是替换现有文档字段时,以美元($)为前缀的字段可以是顶级字段名。Subfields can be accessed directly, but you need a helper method to access the top level fields.子字段可以直接访问,但您需要一个辅助方法来访问顶级字段。

Tip

See also: 另请参阅:

$getField, $setField, $literal, $replaceWith

Consider a collection with documents like this inventory record:考虑一个包含类似以下inventory记录的文档的集合:

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

The pricing.$discount subfield can be queried directly.pricing.$discount子字段可以直接查询。

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

Use $getField and $literal to access the value of the top level $bin field.使用$getField$literal访问顶级$bin字段的值。

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

Updates Using Aggregation Pipelines使用聚合管道的更新

Use $setField, $getField, and $literal in the $replaceWith stage to modify dollar ($) prefixed fields in an aggregation pipeline.$replaceWith阶段中使用$setField$getField$literal可以修改聚合管道中以美元($)为前缀的字段。

Consider a collection of school records like:考虑一组学校记录,如:

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

Create a new collection for the spring semester using a pipeline to update the dollar ($) prefixed $term field.使用管道为春季学期创建一个新集合,以更新以美元($)为前缀的$term字段。

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

General Restrictions一般限制

In addition to the storage validation rules above, there are some general restrictions on using dollar ($) prefixed field names. 除了上面的存储验证规则之外,对于使用以美元($)为前缀的字段名,还有一些常规限制。These fields cannot:这些字段不能:

  • Be indexed编制索引
  • Be used as part of a shard key用作分片键的一部分
  • Be validated using $jsonSchema使用$jsonSchema进行验证
  • Be be modified with an escape sequence使用转义序列进行修改
  • Be used with Field Level Encryption字段级加密一起使用
  • Be used as a subfield in an _id document用作_id文档中的子字段
Warning

Possible Data Loss With Dollar Signs ($) and Periods (.)美元符号($)和句点(.)可能的数据丢失

There is a small chance of data loss when using dollar ($) prefixed field names or field names that contain periods (.) if these field names are used in conjunction with unacknowledged writes (write concern w=0) on servers that are older than MongoDB 5.0.在MongoDB 5.0以前的服务器上,如果使用以美元($)为前缀的字段名或包含句点(.)的字段名与未确认的写入(写入关注w=0)一起使用,则数据丢失的可能性很小。

When running insert, update, and findAndModify commands, drivers that are 5.0 compatible remove restrictions on using documents with field names that are dollar ($) prefixed or that contain periods (.). These field names generated a client-side error in earlier driver versions.当运行insertupdatefindAndModify命令时,与5.0兼容的驱动程序将删除对使用字段名称以美元($)为前缀或包含句点(.)的文档的限制。这些字段名称在早期的驱动程序版本中生成了客户端错误。

The restrictions are removed regardless of the server version the driver is connected to. 无论驱动程序连接到哪个服务器版本,都会删除这些限制。If a 5.0 driver sends a document to an older server, the document will be rejected without sending an error.如果5.0驱动程序将文档发送到较旧的服务器,则该文档将被拒绝而不会发送错误。

Warning

Import and Export Concerns With Dollar Signs ($) and Periods (.)美元符号($)和点号(.)的导入导出问题

Starting in MongoDB 5.0, document field names can be dollar ($) prefixed and can contain periods (.). 从MongoDB 5.0开始,文档字段名称可以是美元($)前缀,并且可以包含句点(.)。However, mongoimport and mongoexport may not work as expected in some situations with field names that make use of these characters.但是,对于使用这些字符的字段名,mongoimportmongoexport在某些情况下可能无法正常工作。

MongoDB Extended JSON v2 cannot differentiate between type wrappers and fields that happen to have the same name as type wrappers. MongoDB Extended JSON v2无法区分类型包装器和碰巧与类型包装器同名的字段。Do not use Extended JSON formats in contexts where the corresponding BSON representations might include dollar ($) prefixed keys. 在相应的BSON表示可能包括以美元($)为前缀的键的上下文中,不要使用扩展JSON格式。The DBRef mechanism is an exception to this general rule.DBRef机制是这个一般规则的一个例外。

There are also restrictions on using mongoimport and mongoexport with periods (.) in field names. 在字段名称中使用带句点(.)的mongoimportmongoexport也有限制。Since CSV files use the period (.) to represent data hierarchies, a period (.) in a field name will be misinterpreted as a level of nesting.由于CSV文件使用句点(.)表示数据层次结构,因此字段名称中的句点(..)将被误解为嵌套级别。