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

On this page本页内容

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期间创建新文档的更新被视为insert,而不是字段名验证的updateUpserts can accept dollar ($) prefixed fields. Upserts可以接受带美元($)前缀的字段。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.但是,upserts是一种特殊情况,如果更新的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: 参阅:

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:考虑一个school记录集合,比如:

{
   "_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 (.). 当运行insertupdatefindAndModify命令时,与5.0兼容的驱动程序将取消对使用字段名前缀为美元($)或包含句点(.)的文档的限制。These field names generated a client-side error in earlier driver versions.这些字段名在早期驱动程序版本中生成了客户端错误。

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. 无法区分类型包装和恰好与类型包装同名的字段。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文件使用句点(.)要表示数据层次结构,请使用句点(.)在字段中,名称将被误解为嵌套级别。

←  Distributed QueriesRead Isolation, Consistency, and Recency →