# MongoDB中文手册|官方文档中文版

![](/files/yOnEe9izCcGdORts5Lo3)

[MongoDB 官网](https://www.mongodb.com/) | [MongoDB中文社区网站](https://mongoing.com/) | [Tapdata 数据同步工具](https://sourl.cn/zwqNLq)

## 项目介绍

MongoDB是专为可扩展性，高性能和高可用性而设计的数据库。它可以从单服务器部署扩展到大型、复杂的多数据中心架构。利用内存计算的优势，MongoDB能够提供高性能的数据读写操作。 MongoDB的本地复制和自动故障转移功能使您的应用程序具有企业级的可靠性和操作灵活性。

[MongoDB中文社区](https://mongoing.com/)是一个MongoDB中文爱好者交流平台，由来自MongoDB官方和国内前沿IT互联网公司的MongoDB专家组成，着力于为更多mongoers带来MongoDB最新资讯和一手实践干货！官方文档翻译为MongoDB中文社区的一个版块，主要由[社区翻译小组](https://mongoing.com/translators)进行维护。希望我们的努力能为大家带来权威可靠的中文文档！

本项目为MongoDB官方文档的中文版，与[官方文档](https://docs.mongodb.com/manual/)保持同步。

| 内容                                                                                                  | 说明                                                                                                                    |
| --------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| 本手册文档版本                                                                                             | 基于4.2版本，不断与官方最新版保持同步。                                                                                                 |
| 维护地址                                                                                                | [mongodb-china Github](https://github.com/mongodb-china/MongoDB-CN-Manual)                                            |
| 中文文档在线阅读                                                                                            | [MongoDB中文社区文档在线阅读](https://docs.mongoing.com/) ; [上海锦木文档在线阅读](https://docs.jinmu.info/MongoDB-Manual-zh/)            |
| 在线阅读问题报告                                                                                            | 如果您发现问题，请在 [MongoDB-Manual-zh/issues](https://github.com/mongodb-china/MongoDB-CN-Manual/issues)上提 issue              |
| [文档翻译贡献者名单](https://github.com/mongodb-china/MongoDB-CN-Manual/blob/master/List-of-contributors.md) | [MongoDB中文社区](https://mongoing.com/)& [上海锦木](http://www.jinmuinfo.com/)已完成大部分翻译，欢迎更多mongoers加入                        |
| 如何加入文档翻译                                                                                            | 点击[文档翻译认领列表](https://github.com/mongodb-china/MongoDB-CN-Manual/blob/master/Document-translation-claim-list.md)加入文档翻译 |
| 文档翻译规范                                                                                              | [贡献指南](https://github.com/mongodb-china/MongoDB-CN-Manual/blob/master/CONTRIBUTING.md)                                |
| 加入翻译权益                                                                                              | <p>翻译内容将由MongoDB中文社区专家进行审核，</p><p>审核通过后将保留署名权发布到本手册及MongoDB中文社区微信内容平台。</p>                                            |

## LICENSE

本项目为署名-非商业性使用-相同方式共享 [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)

## MongoDB中文社区

| 资源列表推荐             | 资源入口                                                                                                                                                                                                                                                                       |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| MongoDB中文社区官网      | <https://mongoing.com/>                                                                                                                                                                                                                                                    |
| 微信服务号 ——最新资讯和优质文章  | Mongoing中文社区（mongoing-mongoing）                                                                                                                                                                                                                                            |
| 微信订阅号 ——发布文档翻译内容   | MongoDB中文用户组（mongoing123）                                                                                                                                                                                                                                                  |
| 官方微信号 —— 官方最新资讯    | MongoDB数据库（MongoDB-China）                                                                                                                                                                                                                                                  |
| MongoDB中文社区组委会成员介绍 | <https://mongoing.com/core-team-members>                                                                                                                                                                                                                                   |
| MongoDB中文社区翻译小组介绍  | <https://mongoing.com/translators>                                                                                                                                                                                                                                         |
| MongoDB中文社区微信技术交流群 | 添加社区助理小芒果微信（ID:mongoingcom），并备注 mongo                                                                                                                                                                                                                                      |
| MongoDB中文社区会议及文档资源 | <https://mongoing.com/resources>                                                                                                                                                                                                                                           |
| MongoDB中文社区大咖博客    | [基础知识](https://mongoing.com/basic-knowledge) [性能优化](https://mongoing.com/performance-optimization) [原理解读](https://mongoing.com/interpretation-of-principles) [运维监控](https://mongoing.com/operation-and-maintenance-monitoring) [最佳实践](https://mongoing.com/best-practices) |
| MongoDB白皮书         | <https://mongoing.com/mongodb-download-white-paper>                                                                                                                                                                                                                        |
| MongoDB初学者教程-7天入门  | <https://mongoing.com/mongodb-beginner-tutorial>                                                                                                                                                                                                                           |
| 社区活动通知邮件订阅         | <http://mongoingmongoing.mikecrm.com/tlAwSHM>                                                                                                                                                                                                                              |


# MongoDB用户手册说明

MONGODB 4.2发布于2019年8月13日

有关MongoDB 4.2中的新功能，请参阅MongoDB 4.2 [发行说明](https://docs.mongodb.com/v4.2/release-notes/4.2/)。

欢迎使用MongoDB 4.2手册！MongoDB是一个文档数据库，旨在简化开发和扩展。该手册介绍了MongoDB中的关键概念，介绍了查询语言，并提供了操作和管理方面的考虑因素和过程以及全面的参考部分。该手册也以[HTML tar.gz](https://docs.mongodb.com/v4.2/manual.tar.gz)和[EPUB的形式提供](https://docs.mongodb.com/v4.2/MongoDB-manual.epub)。

MongoDB提供数据库的\_社区\_版和\_企业\_版：

* MongoDB社区版是MongoDB的[开源和免费](https://github.com/mongodb/mongo/)版本。
* MongoDB企业版作为MongoDB高级企业版订阅的一部分提供，并包括对MongoDB部署的全面支持。MongoDB企业版还添加了以企业为中心的功能，例如LDAP和Kerberos支持，磁盘上的加密以及审计。

MongoDB还提供 [Atlas](https://www.mongodb.com/cloud/atlas?tck=docs_server)（云中托管的MongoDB企业版服务选项），无需安装开销，并提供免费的入门套餐。

该手册记录了MongoDB社区版和企业版的特性和功能。

## 入门

MongoDB 在以下版本中提供了“ [入门指南”](https://docs.mongodb.com/getting-started/shell)。

|                                                                                                                                                               |                                                                                                                               |                                                                                                            |                                                                    |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| [mongo Shell版](https://docs.mongodb.com/v4.2/tutorial/getting-started/) [Node.JS版](http://mongodb.github.io/node-mongodb-native/3.4/quick-start/quick-start/) | [Python版](https://docs.mongodb.com/drivers/pymongo) [C ++版](https://mongodb.github.io/mongo-cxx-driver/mongocxx-v3/tutorial/) | [Java版](https://mongodb.github.io/mongo-java-driver/) [C＃版](http://mongodb.github.io/mongo-csharp-driver/) | [Ruby版](https://docs.mongodb.com/ruby-driver/current/quick-start/) |
|                                                                                                                                                               |                                                                                                                               |                                                                                                            |                                                                    |

完成《入门指南》后，您可能会发现以下有用的主题。

| 介绍                                                                                                                                                                                                                                        | 开发者                                                                                                                                                                                                                | 管理员                                                                                                                                                                                                                           | 参考                                                                                                                                                                                                                           |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [MongoDB简介](https://docs.mongodb.com/v4.2/introduction/) [安装指南](https://docs.mongodb.com/v4.2/installation/) [数据库和集合](https://docs.mongodb.com/v4.2/core/databases-and-collections/) [文档资料](https://docs.mongodb.com/v4.2/core/document/) | [CRUD操作](https://docs.mongodb.com/v4.2/crud/) [聚合](https://docs.mongodb.com/v4.2/aggregation/) [SQL到MongoDB](https://docs.mongodb.com/v4.2/reference/sql-comparison/) [索引](https://docs.mongodb.com/v4.2/indexes/) | [生产须知](https://docs.mongodb.com/v4.2/administration/production-notes/) [副本集](https://docs.mongodb.com/v4.2/replication/) [分片集群](https://docs.mongodb.com/v4.2/sharding/) [MongoDB安全](https://docs.mongodb.com/v4.2/security/) | [shell方法](https://docs.mongodb.com/v4.2/reference/method/) [查询运算符](https://docs.mongodb.com/v4.2/reference/operator/) [参考](https://docs.mongodb.com/v4.2/reference/)[词汇表](https://docs.mongodb.com/v4.2/reference/glossary/) |

## 支持

### MongoDB社区

如有疑问，讨论或常规技术支持，请访问 [MongoDB社区论坛](https://community.mongodb.com/)。MongoDB社区论坛是与其他MongoDB用户联系，提出问题并获得答案的集中场所。

> 译者注：MongoDB中文社区提供MongoDB中文用户原创博客/文档翻译/技术问答/技术大会/线上活动等板块平台交流服务，访问MongoDB中文社区网站请点击：<https://mongoing.com/> 进入技术交流社群请联系小芒果，微信ID：mongoingcom

### MongoDB Atlas或Cloud

如有技术支持问题，请登录您的[MongoDB Cloud帐户](https://cloud.mongodb.com/user)并打开工单。

### MongoDB Enterprise或Ops Manager

如有技术支持问题，请通过[MongoDB支持门户](https://support.mongodb.com/)提交工单 。

## 问题

有关如何为MongoDB服务或相关项目之一提交JIRA工单的说明，请参阅 <https://github.com/mongodb/mongo/wiki/Submit-Bug-Reports。>

## 社区

参与MongoDB社区是与其他才华横溢，志趣相投的工程师建立关系，提高对正在从事的有趣工作的认识并提高技能的一种好方法。要了解MongoDB社区，请参阅 [参与MongoDB](http://www.mongodb.org/get-involved?tck=docs_server)。

> 译者注：MongoDB中文社区提供MongoDB中文用户原创博客/文档翻译/技术问答/技术大会/线上活动等板块平台交流服务，访问MongoDB中文社区网站请点击：<https://mongoing.com/> 进入技术交流社群请联系小芒果，微信ID：mongoingcom

## 学习

除了文档外，还有许多学习使用MongoDB的方法。您可以：

* 在[MongoDB大学](https://university.mongodb.com/?tck=docs_server)注册免费的在线课程
* 浏览[MongoDB演示文稿](https://www.mongodb.com/presentations?tck=docs_server)的存档
* 加入本地的[MongoDB用户组（MUG）](https://www.mongodb.org/user-groups?tck=docs_server)
* 参加即将举行的MongoDB [活动](http://www.mongodb.com/events?tck=docs_server)或 [网络研讨会](http://www.mongodb.com/webinars?tck=docs_server)
* 阅读[MongoDB博客](http://www.mongodb.com/blog?tck=docs_server)
* 下载[架构指南](https://www.mongodb.com/lp/whitepaper/architecture-guide?tck=docs_server)

## 许可

该手册已根据[知识共享署名-非商业性-相同方式共享3.0美国许可证进行了许可](http://creativecommons.org/licenses/by-nc-sa/3.0/us/)

有关MongoDB许可的信息，请参阅[MongoDB许可](https://www.mongodb.org/about/licensing/)。

## 其他资源

* [MongoDB，Inc.](https://www.mongodb.com/?tck=docs_server)

  MongoDB背后的公司。
* [MongoDB Atlas](https://www.mongodb.com/cloud?tck=docs_server)

  数据库即服务。
* [MongoDB Cloud Manager](https://www.mongodb.com/cloud/cloud-manager/?tck=docs_server)

  适用于MongoDB的基于云的托管运营管理解决方案。
* [MongoDB Ops Manager](https://docs.opsmanager.mongodb.com/current/?tck=docs_server)

  MongoDB的企业运营管理解决方案：包括自动化，备份和监控。
* [MongoDB生态系统](https://docs.mongodb.com/ecosystem/?tck=docs_server)

  可用于MongoDB的驱动程序，框架，工具和服务的文档。

原文链接：<https://docs.mongodb.com/v4.2/>

### MongoDB中文社区

![MongoDB中文社区—MongoDB爱好者技术交流平台](https://mongoing.com/wp-content/uploads/2020/09/6de8a4680ef684d-2.png)

| 资源列表推荐             | 资源入口                                                                                                                                                                                                                                                                       |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| MongoDB中文社区官网      | <https://mongoing.com/>                                                                                                                                                                                                                                                    |
| 微信服务号 ——最新资讯和优质文章  | Mongoing中文社区（mongoing-mongoing）                                                                                                                                                                                                                                            |
| 微信订阅号 ——发布文档翻译内容   | MongoDB中文用户组（mongoing123）                                                                                                                                                                                                                                                  |
| 官方微信号 —— 官方最新资讯    | MongoDB数据库（MongoDB-China）                                                                                                                                                                                                                                                  |
| MongoDB中文社区组委会成员介绍 | <https://mongoing.com/core-team-members>                                                                                                                                                                                                                                   |
| MongoDB中文社区翻译小组介绍  | <https://mongoing.com/translators>                                                                                                                                                                                                                                         |
| MongoDB中文社区微信技术交流群 | 添加社区助理小芒果微信（ID:mongoingcom），并备注 mongo                                                                                                                                                                                                                                      |
| MongoDB中文社区会议及文档资源 | <https://mongoing.com/resources>                                                                                                                                                                                                                                           |
| MongoDB中文社区大咖博客    | [基础知识](https://mongoing.com/basic-knowledge) [性能优化](https://mongoing.com/performance-optimization) [原理解读](https://mongoing.com/interpretation-of-principles) [运维监控](https://mongoing.com/operation-and-maintenance-monitoring) [最佳实践](https://mongoing.com/best-practices) |
| MongoDB白皮书         | <https://mongoing.com/mongodb-download-white-paper>                                                                                                                                                                                                                        |
| MongoDB初学者教程-7天入门  | <https://mongoing.com/mongodb-beginner-tutorial>                                                                                                                                                                                                                           |
| 社区活动邮件订阅           | <https://sourl.cn/spszjN>                                                                                                                                                                                                                                                  |


# MongoDB简介

在本页

* [文档数据库](https://docs.mongodb.com/v4.2/introduction/#document-database)
* [主要特性](https://docs.mongodb.com/v4.2/introduction/#key-features)

欢迎使用MongoDB 4.2手册！MongoDB是一个文档数据库，旨在简化开发和扩展。该手册介绍了MongoDB中的关键概念，介绍了查询语言，并提供了操作和管理上的注意事项和过程以及全面的参考章节。

MongoDB提供数据库的\_社区\_版和\_企业\_版：

* MongoDB社区版是MongoDB的[可用源和免费](https://github.com/mongodb/mongo/)版本。
* MongoDB企业版作为MongoDB高级企业版订阅的一部分提供，并且包括对MongoDB部署的全面支持。MongoDB企业版还添加了以企业为中心的功能，例如LDAP和Kerberos支持，磁盘加密和审核。

## 文档数据库

MongoDB中的记录是一个文档，它是由字段和值对组成的数据结构。MongoDB文档类似于JSON对象。字段的值可以包括其他文档，数组和文档数组。

![A MongoDB document.](https://docs.mongodb.com/v4.2/_images/crud-annotated-document.bakedsvg.svg)

使用文档的优点是：

* 文档（即对象）对应于许多编程语言中的内置数据类型。
* 嵌入式文档和数组减少了对昂贵连接的需求。
* 动态模式支持流畅的多态性。

### 集合/视图/按需实例化视图

MongoDB将文档存储在[集合中](https://docs.mongodb.com/v4.2/core/databases-and-collections/#collections)。集合类似于关系数据库中的表。

除集合外，MongoDB还支持：

* 只读[视图](https://docs.mongodb.com/v4.2/core/views/)（从MongoDB 3.4开始）
* [按需实例化视图](https://docs.mongodb.com/v4.2/core/materialized-views/)（从MongoDB 4.2开始）。

## 主要特性

### 高性能

MongoDB提供高性能的数据持久化。特别是，

* 对嵌入式数据模型的支持减少了数据库系统上的I / O操作。
* 索引支持更快的查询，并且可以包含来自嵌入式文档和数组的键。

### 丰富的查询语言

MongoDB支持丰富的查询语言以支持[读写操作（CRUD）](https://docs.mongodb.com/v4.2/crud/)以及：

* [数据聚合](https://docs.mongodb.com/v4.2/core/aggregation-pipeline/)
* [文本搜索](https://docs.mongodb.com/v4.2/text-search/)和[地理空间查询](https://docs.mongodb.com/v4.2/tutorial/geospatial-tutorial/)。

也可以看看

* [SQL到MongoDB的映射图](https://docs.mongodb.com/v4.2/reference/sql-comparison/)
* [SQL到聚合的映射图](https://docs.mongodb.com/v4.2/reference/sql-aggregation-comparison/)

### 高可用

MongoDB的复制工具（称为[副本集](https://docs.mongodb.com/v4.2/replication/)）提供：

* \_自动\_故障转移
* 数据冗余。

[副本集](https://docs.mongodb.com/v4.2/replication/)是一组维护相同数据集合的 mongod实例，提供了冗余和提高了数据可用性。

### 水平拓展

MongoDB提供水平可伸缩性作为其\_核心\_ 功能的一部分：

* [分片](https://docs.mongodb.com/v4.2/sharding/#sharding-introduction)将数据分布在一个集群的机器上。
* 从3.4开始，MongoDB支持基于[分片键](https://docs.mongodb.com/v4.2/reference/glossary/#term-shard-key)创建数据[区域](https://docs.mongodb.com/v4.2/core/zone-sharding/#zone-sharding)。在平衡群集中，MongoDB仅将区域覆盖的读写定向到区域内的那些分片。有关 更多信息，请参见[区域](https://docs.mongodb.com/v4.2/core/zone-sharding/#zone-sharding)章节。

### 支持多种存储引擎

MongoDB支持[多个存储引擎](https://docs.mongodb.com/v4.2/core/storage-engines/)：

* [WiredTiger存储引擎](https://docs.mongodb.com/v4.2/core/wiredtiger/)（包括对[静态](https://docs.mongodb.com/v4.2/core/wiredtiger/)[加密的](https://docs.mongodb.com/v4.2/core/security-encryption-at-rest/)支持 ）
* [内存存储引擎](https://docs.mongodb.com/v4.2/core/inmemory/)。

另外，MongoDB提供可插拔的存储引擎API，允许第三方为MongoDB开发存储引擎。

← [MongoDB手册内容](https://docs.mongodb.com/v4.2/contents/)

原文链接：<https://docs.mongodb.com/v4.2/introduction/>

### MongoDB中文社区

![MongoDB中文社区—MongoDB爱好者技术交流平台](https://mongoing.com/wp-content/uploads/2020/09/6de8a4680ef684d-2.png)

| 资源列表推荐             | 资源入口                                                                                                                                                                                                                                                                       |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| MongoDB中文社区官网      | <https://mongoing.com/>                                                                                                                                                                                                                                                    |
| 微信服务号 ——最新资讯和优质文章  | Mongoing中文社区（mongoing-mongoing）                                                                                                                                                                                                                                            |
| 微信订阅号 ——发布文档翻译内容   | MongoDB中文用户组（mongoing123）                                                                                                                                                                                                                                                  |
| 官方微信号 —— 官方最新资讯    | MongoDB数据库（MongoDB-China）                                                                                                                                                                                                                                                  |
| MongoDB中文社区组委会成员介绍 | <https://mongoing.com/core-team-members>                                                                                                                                                                                                                                   |
| MongoDB中文社区翻译小组介绍  | <https://mongoing.com/translators>                                                                                                                                                                                                                                         |
| MongoDB中文社区微信技术交流群 | 添加社区助理小芒果微信（ID:mongoingcom），并备注 mongo                                                                                                                                                                                                                                      |
| MongoDB中文社区会议及文档资源 | <https://mongoing.com/resources>                                                                                                                                                                                                                                           |
| MongoDB中文社区大咖博客    | [基础知识](https://mongoing.com/basic-knowledge) [性能优化](https://mongoing.com/performance-optimization) [原理解读](https://mongoing.com/interpretation-of-principles) [运维监控](https://mongoing.com/operation-and-maintenance-monitoring) [最佳实践](https://mongoing.com/best-practices) |
| MongoDB白皮书         | <https://mongoing.com/mongodb-download-white-paper>                                                                                                                                                                                                                        |
| MongoDB初学者教程-7天入门  | <https://mongoing.com/mongodb-beginner-tutorial>                                                                                                                                                                                                                           |
| 社区活动邮件订阅           | <https://sourl.cn/spszjN>                                                                                                                                                                                                                                                  |


# 入门

下方页面提供了在MongoDB Shell中进行查询的各种示例。有关使用MongoDB驱动程序的示例，请参阅“ [其他示例”](https://docs.mongodb.com/v4.2/tutorial/getting-started/#gs-additional-examples)部分中的链接。

## 示例

在 [shell](https://docs.mongodb.com/v4.2/tutorial/getting-started/#mongo-web-shell)内单击以进行连接。连接后，您可以在上面的 [shell](https://docs.mongodb.com/v4.2/tutorial/getting-started/#mongo-web-shell)中运行示例。

#### 切换数据库

在[shell中](https://docs.mongodb.com/v4.2/tutorial/getting-started/#mongo-web-shell)，`db`是指您当前的数据库。键入`db`以显示当前数据库。

复制

```
db
```

该操作应返回`test`，这是默认数据库。

要切换数据库，请键入 `use <db>`。例如，要切换到 `examples` 数据库：

复制

```
use examples
```

切换之前您无需创建数据库。当您第一次在数据库中存储数据时（例如在数据库中创建第一个集合），MongoDB会创建数据库。

要验证您的数据库现在是`examples`，在上面的[shell中](https://docs.mongodb.com/v4.2/tutorial/getting-started/#mongo-web-shell)键入`db`。

复制

```
db
```

要在数据库中创建集合，请参见下一个选项卡。

> 译者注：填充一个集合（插入）/选择所有文档/指定平等匹配/指定要返回的字段（投影）相关操作请到原文查看和复制代码。
>
> 链接：<https://docs.mongodb.com/v4.2/tutorial/getting-started/>

## 下一步

### 建立自己的部署

要设置自己的部署：

|                     |                                                                                                                |
| ------------------- | -------------------------------------------------------------------------------------------------------------- |
| MongoDB Atlas免费套餐集群 | MongoDB Atlas是一种快速，便捷，免费的MongoDB入门途径。要了解更多信息，请参阅 [Atlas入门](https://docs.atlas.mongodb.com/getting-started/)教程。 |
| 本地MongoDB安装         | 有关在本地安装MongoDB的更多信息，请参阅 [安装MongoDB](https://docs.mongodb.com/v4.2/installation/#tutorial-installation)。        |

### 其他示例

有关其他示例，包括MongoDB驱动程序特定的示例（Python，Java，Node.js等），请参阅：

|        |                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 查询文档示例 | [查询文档](https://docs.mongodb.com/v4.2/tutorial/query-documents/) [查询嵌入/嵌套文档](https://docs.mongodb.com/v4.2/tutorial/query-embedded-documents/) [查询数组](https://docs.mongodb.com/v4.2/tutorial/query-arrays/) [查询嵌入式文档数组](https://docs.mongodb.com/v4.2/tutorial/query-array-of-documents/) [从查询返回的项目字段](https://docs.mongodb.com/v4.2/tutorial/project-fields-from-query-results/) [查询空字段或缺少字段](https://docs.mongodb.com/v4.2/tutorial/query-for-null-fields/) |
| 更新文档示例 | [更新文档](https://docs.mongodb.com/v4.2/tutorial/update-documents/)                                                                                                                                                                                                                                                                                                                                                                                             |
| 删除文档示例 | [删除文档](https://docs.mongodb.com/v4.2/tutorial/remove-documents/)                                                                                                                                                                                                                                                                                                                                                                                             |

### 其他主题

| 介绍                                                                                                                                                                                                                                        | 开发者                                                                                                                                                                                                                | 管理员                                                                                                                                                                                                                           | 参考                                                                                                                                                                                                                            |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [MongoDB简介](https://docs.mongodb.com/v4.2/introduction/) [安装指南](https://docs.mongodb.com/v4.2/installation/) [数据库和集合](https://docs.mongodb.com/v4.2/core/databases-and-collections/) [文档资料](https://docs.mongodb.com/v4.2/core/document/) | [CRUD操作](https://docs.mongodb.com/v4.2/crud/) [聚合](https://docs.mongodb.com/v4.2/aggregation/) [SQL到MongoDB](https://docs.mongodb.com/v4.2/reference/sql-comparison/) [索引](https://docs.mongodb.com/v4.2/indexes/) | [生产须知](https://docs.mongodb.com/v4.2/administration/production-notes/) [副本集](https://docs.mongodb.com/v4.2/replication/) [分片集群](https://docs.mongodb.com/v4.2/sharding/) [MongoDB安全](https://docs.mongodb.com/v4.2/security/) | [Shell方法](https://docs.mongodb.com/v4.2/reference/method/) [查询运算符](https://docs.mongodb.com/v4.2/reference/operator/) [参考](https://docs.mongodb.com/v4.2/reference/) [词汇表](https://docs.mongodb.com/v4.2/reference/glossary/) |

原文链接：<https://docs.mongodb.com/v4.2/tutorial/getting-started/>

译者：小芒果


# 数据库和集合

在本页面

* [数据库](https://docs.mongodb.com/v4.2/core/databases-and-collections/#databases)
* [集合](https://docs.mongodb.com/v4.2/core/databases-and-collections/#collections)

MongoDB将[BSON文档](https://docs.mongodb.com/v4.2/core/document/#bson-document-format)（即数据记录）存储在[集合中](https://docs.mongodb.com/v4.2/reference/glossary/#term-collection)；数据库中的集合。

![A collection of MongoDB documents.](https://docs.mongodb.com/v4.2/_images/crud-annotated-collection.bakedsvg.svg)

## 数据库

在MongoDB中，文档集合存在数据库中。

要选择使用的数据库，请在[`mongo`](https://docs.mongodb.com/v4.2/reference/program/mongo/#bin.mongo)shell程序中发出 `use <db>` 语句，如下方示例：

复制

```
use myDB
```

### 创建数据库

如果数据库不存在，则在您第一次为该数据库存储数据时，MongoDB会创建该数据库。这样，您可以切换到不存在的数据库并在[`mongo`](https://docs.mongodb.com/v4.2/reference/program/mongo/#bin.mongo)shell中执行以下操作 ：

复制

```
use myNewDB

db.myNewCollection1.insertOne( { x: 1 } )
```

该[`insertOne()`](https://docs.mongodb.com/v4.2/reference/method/db.collection.insertOne/#db.collection.insertOne)操作将同时创建数据库`myNewDB`和集合`myNewCollection1`（如果它们尚不存在）。确保数据库名称和集合名称均遵循MongoDB [命名限制](https://docs.mongodb.com/v4.2/reference/limits/#restrictions-on-db-names)。

## 集合

MongoDB将文档存储在集合中。集合类似于关系数据库中的表。

### 创建集合

如果不存在集合，则在您第一次为该集合存储数据时，MongoDB会创建该集合。

复制

```
db.myNewCollection2.insertOne( { x: 1 } )
db.myNewCollection3.createIndex( { y: 1 } )
```

如果[`insertOne()`](https://docs.mongodb.com/v4.2/reference/method/db.collection.insertOne/#db.collection.insertOne)和 [`createIndex()`](https://docs.mongodb.com/v4.2/reference/method/db.collection.createIndex/#db.collection.createIndex)操作都还不存在，则会创建它们各自的集合。确保集合名称遵循MongoDB [命名限制](https://docs.mongodb.com/v4.2/reference/limits/#restrictions-on-db-names)。

### 显示创建

MongoDB提供了[`db.createCollection()`](https://docs.mongodb.com/v4.2/reference/method/db.createCollection/#db.createCollection)使用各种选项显式创建集合的方法，例如设置最大大小或文档验证规则。如果未指定这些选项，则无需显式创建集合，因为在首次存储集合数据时，MongoDB会创建新集合。

要修改这些收集选项，请参见[`collMod`](https://docs.mongodb.com/v4.2/reference/command/collMod/#dbcmd.collMod)。

### 文档验证

*3.2版中的新功能。*

默认情况下，集合不要求其文档具有相同的模式。也就是说，单个集合中的文档不需要具有相同的字段集，并且字段的数据类型可以在集合中的不同文档之间有所不同。

但是，从MongoDB 3.2开始，您可以在更新和插入操作期间对集合强制执行[文档验证规则](https://docs.mongodb.com/v4.2/core/schema-validation/)。有关详细信息，请参见[模式验证](https://docs.mongodb.com/v4.2/core/schema-validation/)。

### 修改文档结构

要更改集合中文档的结构，例如添加新字段，删除现有字段或将字段值更改为新类型，请将文档更新为新结构。

### 唯一标识符

*3.6版的新功能。*

注意

在`featureCompatibilityVersion`必须设置为`"3.6"`或更大。有关更多信息，请参见[View FeatureCompatibilityVersion](https://docs.mongodb.com/v4.2/reference/command/setFeatureCompatibilityVersion/#view-fcv)。

集合被分配了一个不变的UUID。副本集的所有成员和分片群集中的分片的集合UUID均相同。

要检索集合的UUID，请运行 [listCollections](https://docs.mongodb.com/manual/reference/command/listCollections)命令或[`db.getCollectionInfos()`](https://docs.mongodb.com/v4.2/reference/method/db.getCollectionInfos/#db.getCollectionInfos)方法。

原文链接：<https://docs.mongodb.com/v4.2/core/databases-and-collections/>

译者：小芒果


# 视图

*3.4 版本新功能*

本页索引

* [创建视图](https://docs.mongodb.com/manual/core/views/#创建视图)
* [表现](https://docs.mongodb.com/manual/core/views/#表现)
* [删除视图](https://docs.mongodb.com/manual/core/views/#删除视图)
* [修改视图](https://docs.mongodb.com/manual/core/views/#修改视图)
* [支持操作](https://docs.mongodb.com/manual/core/views/#支持操作)

从 3.4 开始, MongoDB 添加了基于已存在的集合或者 View (视图) 创建只读的 View 支持.

## 创建视图

创建或者定义一个视图, MongoDB 3.4 的介绍是:

* the `viewOn` and `pipeline`options to the existing[`create`](https://docs.mongodb.com/manual/reference/command/create/#dbcmd.create)command (and[`db.createCollection`](https://docs.mongodb.com/manual/reference/method/db.createCollection/#db.createCollection)helper):

  ```
  db.runCommand( { create: <view>, viewOn: <source>, pipeline: <pipeline> } )
  ```

  or if specifying a default[collation](https://docs.mongodb.com/manual/release-notes/3.4/#relnotes-collation)for the view:

  ```
  db.runCommand( { create: <view>, viewOn: <source>, pipeline: <pipeline>, collation: <collation> } )
  ```
* a new[`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo)shell helper[`db.createView()`](https://docs.mongodb.com/manual/reference/method/db.createView/#db.createView):

  ```
  db.createView(<view>, <source>, <pipeline>, <collation> )
  ```

## 表现

视图具备以下几种表现:

### 只读

视图是只读的; 通过视图进行写操作会报错.

以下为支持视图的读操作:

* [`db.collection.find()`](https://docs.mongodb.com/manual/reference/method/db.collection.find/#db.collection.find)
* [`db.collection.findOne()`](https://docs.mongodb.com/manual/reference/method/db.collection.findOne/#db.collection.findOne)
* [`db.collection.aggregate()`](https://docs.mongodb.com/manual/reference/method/db.collection.aggregate/#db.collection.aggregate)
* [`db.collection.count()`](https://docs.mongodb.com/manual/reference/method/db.collection.count/#db.collection.count)
* [`db.collection.distinct()`](https://docs.mongodb.com/manual/reference/method/db.collection.distinct/#db.collection.distinct)

### 索引使用 & 排序操作

* 视图使用其上游集合的索引.
* 由于索引是基于集合的, 所以你不能基于视图创建, 删除或重建索引, 也不能获取视图的索引列表.
* 你不能指定 [`$natural`](https://docs.mongodb.com/manual/reference/operator/meta/natural/#metaOp._S_natural) 排序.

  例如, 下列操作是 *错误的*:

  ```
  db.view.find().sort({$natural: 1})
  ```

### Project 限制

视图上的 [`find()`](https://docs.mongodb.com/manual/reference/method/db.collection.find/#db.collection.find) 方法不支持如下[projection](https://docs.mongodb.com/manual/reference/operator/projection/) 操作:

* [`$`](https://docs.mongodb.com/manual/reference/operator/projection/positional/#proj._S_)
* [`$elemMatch`](https://docs.mongodb.com/manual/reference/operator/projection/elemMatch/#proj._S_elemMatch)
* [`$slice`](https://docs.mongodb.com/manual/reference/operator/projection/slice/#proj._S_slice)
* [`$meta`](https://docs.mongodb.com/manual/reference/operator/projection/meta/#proj._S_meta)

### 不能改变名称

你不能重命名[视图](/mongo-introduction/databases-and-collections/views).

### 视图创建

* 视图是在读操作期间根据需要实时计算的, 同时 MongoDB 基于视图的读操作是底层聚合管道 (aggregation pipeline) 的一部分. 因此, 视图不支持一下操作:
  * [`db.collection.mapReduce()`](https://docs.mongodb.com/manual/reference/method/db.collection.mapReduce/#db.collection.mapReduce),
  * [`$text`](https://docs.mongodb.com/manual/reference/operator/query/text/#op._S_text) 操作, 因为 `$text` 只在聚合的第一阶段有效,
  * [`geoNear`](https://docs.mongodb.com/manual/reference/command/geoNear/#dbcmd.geoNear) 命令和 [`$geoNear`](https://docs.mongodb.com/manual/reference/operator/aggregation/geoNear/#pipe._S_geoNear)

    管道阶段.
* 如果用于创建视图的聚合管道屏蔽了 `_id` 字段, 那么视图中的文档也会没有 `_id` 字段.

### 分片视图

如果视图依赖的集合是分片的, 那么视图也视为分片的. 因此, 你不能指定分片视图中 [`$lookup`](https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/#pipe._S_lookup) 的 `from`字段与 [`$graphLookup`](https://docs.mongodb.com/manual/reference/operator/aggregation/graphLookup/#pipe._S_graphLookup) 操作.

### Views 与 Collation

* You can specify a default [collation](https://docs.mongodb.com/manual/reference/collation/) for a view at creation time. If no collation is specified, the view’s default collation is the “simple” binary comparison collator. That is, the view does not inherit the collection’s default collation.
* String comparisons on the view use the view’s default collation. An operation that attempts to change or override a view’s default collation will fail with an error.
* If creating a view from another view, you cannot specify a collation that differs from the source view’s collation.
* If performing an aggregation that involves multiple views, such as with [`$lookup`](https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/#pipe._S_lookup) or [`$graphLookup`](https://docs.mongodb.com/manual/reference/operator/aggregation/graphLookup/#pipe._S_graphLookup) , the views must have the same [collation](https://docs.mongodb.com/manual/reference/collation/).

### 公共视图定义

列出集合的操作, 如 [`db.getCollectionInfos()`](https://docs.mongodb.com/manual/reference/method/db.getCollectionInfos/#db.getCollectionInfos) 和 [`db.getCollectionNames()`](https://docs.mongodb.com/manual/reference/method/db.getCollectionNames/#db.getCollectionNames), 的结果中会包括它们的视图.

> IMPORTANT
>
> 视图定义是公开的; 即在视图上的 [`db.getCollectionInfos()`](https://docs.mongodb.com/manual/reference/method/db.getCollectionInfos/#db.getCollectionInfos) 和 `explain` 操作将会包括定义视图的管道. 因此, 请避免直接引用视图定义中敏感的字段和值.

## 删除视图

要删除视图, 请使用视图上的 [`db.collection.drop()`](https://docs.mongodb.com/manual/reference/method/db.collection.drop/#db.collection.drop) 方法.

## 修改视图

你可以通过删除或者重建的方式修改视图, 也可以使用 [`collMod`](https://docs.mongodb.com/manual/reference/command/collMod/#dbcmd.collMod) 命令.

## 支持操作

以下操作支持视图, 除了本文中提到的限制除外:

| 命令                                                                                                                                                                                                                                                    | 方法                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`create`](https://docs.mongodb.com/manual/reference/command/create/#dbcmd.create)                                                                                                                                                                    | [`db.createCollection()`](https://docs.mongodb.com/manual/reference/method/db.createCollection/#db.createCollection) [`db.createView()`](https://docs.mongodb.com/manual/reference/method/db.createView/#db.createView)                                                                                                                                                                                                                                                                                                                                                                                                          |
| [`collMod`](https://docs.mongodb.com/manual/reference/command/collMod/#dbcmd.collMod)                                                                                                                                                                 |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
|                                                                                                                                                                                                                                                       | [`db.getCollection()`](https://docs.mongodb.com/manual/reference/method/db.getCollection/#db.getCollection) [`db.getCollectionInfos()`](https://docs.mongodb.com/manual/reference/method/db.getCollectionInfos/#db.getCollectionInfos) [`db.getCollectionNames()`](https://docs.mongodb.com/manual/reference/method/db.getCollectionNames/#db.getCollectionNames)                                                                                                                                                                                                                                                                |
| [`find`](https://docs.mongodb.com/manual/reference/command/find/#dbcmd.find) [`distinct`](https://docs.mongodb.com/manual/reference/command/distinct/#dbcmd.distinct) [`count`](https://docs.mongodb.com/manual/reference/command/count/#dbcmd.count) | [`db.collection.aggregate()`](https://docs.mongodb.com/manual/reference/method/db.collection.aggregate/#db.collection.aggregate) [`db.collection.find()`](https://docs.mongodb.com/manual/reference/method/db.collection.find/#db.collection.find) [`db.collection.findOne()`](https://docs.mongodb.com/manual/reference/method/db.collection.findOne/#db.collection.findOne) [`db.collection.count()`](https://docs.mongodb.com/manual/reference/method/db.collection.count/#db.collection.count) [`db.collection.distinct()`](https://docs.mongodb.com/manual/reference/method/db.collection.distinct/#db.collection.distinct) |

原文链接：<https://docs.mongodb.com/v4.2/core/views/>

译者 ：王恒


# 按需物化视图

注意

本页的内容讨论了按需物化视图。有关视图的讨论，请参阅[视图](https://docs.mongodb.com/manual/core/views/)。

从4.2版本开始，MongoDB为[aggregation pipeline](https://docs.mongodb.com/manual/core/aggregation-pipeline/)添加了[`$merge`](https://docs.mongodb.com/manual/reference/operator/aggregation/merge/#mongodb-pipeline-pipe.-merge)阶段。此阶段可以将管道结果合并到现有集合中，而不是完全替换现有集合。此功能允许用户创建按需物化视图，每次运行管道时都可以更新输出集合的内容。

## 示例

假设现在接近2019年1月末，集合`bakesales`包含按项目分类的销售信息：

```
db.bakesales.insertMany( [
   { date: new ISODate("2018-12-01"), item: "Cake - Chocolate", quantity: 2, amount: new NumberDecimal("60") },
   { date: new ISODate("2018-12-02"), item: "Cake - Peanut Butter", quantity: 5, amount: new NumberDecimal("90") },
   { date: new ISODate("2018-12-02"), item: "Cake - Red Velvet", quantity: 10, amount: new NumberDecimal("200") },
   { date: new ISODate("2018-12-04"), item: "Cookies - Chocolate Chip", quantity: 20, amount: new NumberDecimal("80") },
   { date: new ISODate("2018-12-04"), item: "Cake - Peanut Butter", quantity: 1, amount: new NumberDecimal("16") },
   { date: new ISODate("2018-12-05"), item: "Pie - Key Lime", quantity: 3, amount: new NumberDecimal("60") },
   { date: new ISODate("2019-01-25"), item: "Cake - Chocolate", quantity: 2, amount: new NumberDecimal("60") },
   { date: new ISODate("2019-01-25"), item: "Cake - Peanut Butter", quantity: 1, amount: new NumberDecimal("16") },
   { date: new ISODate("2019-01-26"), item: "Cake - Red Velvet", quantity: 5, amount: new NumberDecimal("100") },
   { date: new ISODate("2019-01-26"), item: "Cookies - Chocolate Chip", quantity: 12, amount: new NumberDecimal("48") },
   { date: new ISODate("2019-01-26"), item: "Cake - Carrot", quantity: 2, amount: new NumberDecimal("36") },
   { date: new ISODate("2019-01-26"), item: "Cake - Red Velvet", quantity: 5, amount: new NumberDecimal("100") },
   { date: new ISODate("2019-01-27"), item: "Pie - Chocolate Cream", quantity: 1, amount: new NumberDecimal("20") },
   { date: new ISODate("2019-01-27"), item: "Cake - Peanut Butter", quantity: 5, amount: new NumberDecimal("80") },
   { date: new ISODate("2019-01-27"), item: "Tarts - Apple", quantity: 3, amount: new NumberDecimal("12") },
   { date: new ISODate("2019-01-27"), item: "Cookies - Chocolate Chip", quantity: 12, amount: new NumberDecimal("48") },
   { date: new ISODate("2019-01-27"), item: "Cake - Carrot", quantity: 5, amount: new NumberDecimal("36") },
   { date: new ISODate("2019-01-27"), item: "Cake - Red Velvet", quantity: 5, amount: new NumberDecimal("100") },
   { date: new ISODate("2019-01-28"), item: "Cookies - Chocolate Chip", quantity: 20, amount: new NumberDecimal("80") },
   { date: new ISODate("2019-01-28"), item: "Pie - Key Lime", quantity: 3, amount: new NumberDecimal("60") },
   { date: new ISODate("2019-01-28"), item: "Cake - Red Velvet", quantity: 5, amount: new NumberDecimal("100") },
] );
```

### 1.定义按需物化视图

下面的`updateMonthlySales`函数定义了一个`monthlybakesales`物化视图，其中包含累积的每月销售信息。在示例中，该函数采用了一个日期参数来更新从特定日期开始的每月销售信息。

```
updateMonthlySales = function(startDate) {
   db.bakesales.aggregate( [
      { $match: { date: { $gte: startDate } } },
      { $group: { _id: { $dateToString: { format: "%Y-%m", date: "$date" } }, sales_quantity: { $sum: "$quantity"}, sales_amount: { $sum: "$amount" } } },
      { $merge: { into: "monthlybakesales", whenMatched: "replace" } }
   ] );
};
```

* [`$match`](https://docs.mongodb.com/manual/reference/operator/aggregation/match/#mongodb-pipeline-pipe.-match)阶段过滤数据以仅处理那些销售额大于或等于`startDate`
* 阶段按年-月对销售信息进行分组。此阶段输出的文档具有以下形式：

  ```
  { "_id" : "<YYYY-mm>", "sales_quantity" : <num>, "sales_amount" : <NumberDecimal> }
  ```
* [`$merge`](https://docs.mongodb.com/manual/reference/operator/aggregation/merge/#mongodb-pipeline-pipe.-merge)阶段将输出写入到`monthlybakesales`集合

  基于[on](https://docs.mongodb.com/manual/reference/operator/aggregation/merge/#std-label-merge-on)`_id`字段（未分片输出集合的默认值），此阶段会检查聚合结果中的文档是否 [匹配](https://docs.mongodb.com/manual/reference/operator/aggregation/merge/#std-label-merge-whenMatched) 集合中的现有文档：

  * [当匹配时](https://docs.mongodb.com/manual/reference/operator/aggregation/merge/#std-label-merge-whenMatched)（即同年月的文档已经存在于集合中），此阶段会使用来自聚合结果的文档[替换现有文档](https://docs.mongodb.com/manual/reference/operator/aggregation/merge/#std-label-merge-whenMatched-replace)；
  * [当不匹配时](https://docs.mongodb.com/manual/reference/operator/aggregation/merge/#std-label-merge-whenNotMatched)，此阶段将聚合结果中的文档插入到集合中（不匹配时的默认行为）。

### 2. 执行初始运行

对于初始运行，你可以传入一个日期`new ISODate("1970-01-01")`：

```
updateMonthlySales(new ISODate("1970-01-01"));
```

初始运行后，`monthlybakesales`包含以下文档；即`db.monthlybakesales.find().sort( { _id: 1 } )`返回以下内容：

```
{ "_id" : "2018-12", "sales_quantity" : 41, "sales_amount" : NumberDecimal("506") }
{ "_id" : "2019-01", "sales_quantity" : 86, "sales_amount" : NumberDecimal("896") }
```

### 3. 刷新物化视图

假设到了2019年2月的第一周，`bakesales`集合更新了新的销售信息；具体来说就是一月和二月新增的销售。

```
db.bakesales.insertMany( [
   { date: new ISODate("2019-01-28"), item: "Cake - Chocolate", quantity: 3, amount: new NumberDecimal("90") },
   { date: new ISODate("2019-01-28"), item: "Cake - Peanut Butter", quantity: 2, amount: new NumberDecimal("32") },
   { date: new ISODate("2019-01-30"), item: "Cake - Red Velvet", quantity: 1, amount: new NumberDecimal("20") },
   { date: new ISODate("2019-01-30"), item: "Cookies - Chocolate Chip", quantity: 6, amount: new NumberDecimal("24") },
   { date: new ISODate("2019-01-31"), item: "Pie - Key Lime", quantity: 2, amount: new NumberDecimal("40") },
   { date: new ISODate("2019-01-31"), item: "Pie - Banana Cream", quantity: 2, amount: new NumberDecimal("40") },
   { date: new ISODate("2019-02-01"), item: "Cake - Red Velvet", quantity: 5, amount: new NumberDecimal("100") },
   { date: new ISODate("2019-02-01"), item: "Tarts - Apple", quantity: 2, amount: new NumberDecimal("8") },
   { date: new ISODate("2019-02-02"), item: "Cake - Chocolate", quantity: 2, amount: new NumberDecimal("60") },
   { date: new ISODate("2019-02-02"), item: "Cake - Peanut Butter", quantity: 1, amount: new NumberDecimal("16") },
   { date: new ISODate("2019-02-03"), item: "Cake - Red Velvet", quantity: 5, amount: new NumberDecimal("100") }
] )
```

为了刷新1月和2月的`monthlybakesales`数据，需要再次运行该函数以重新运行聚合管道，日期参数值从`new ISODate("2019-01-01")`开始。

```
updateMonthlySales(new ISODate("2019-01-01"));
```

`monthlybakesales`的内容已更新，并能反映出`bakesales`集合中的最新数据；即`db.monthlybakesales.find().sort( { _id: 1 } )`返回以下内容：

```
{ "_id" : "2018-12", "sales_quantity" : 41, "sales_amount" : NumberDecimal("506") }
{ "_id" : "2019-01", "sales_quantity" : 102, "sales_amount" : NumberDecimal("1142") }
{ "_id" : "2019-02", "sales_quantity" : 15, "sales_amount" : NumberDecimal("284") }
```

## 附加信息

[`$merge`](https://docs.mongodb.com/manual/reference/operator/aggregation/merge/#mongodb-pipeline-pipe.-merge)阶段:

* 可以输出到相同或不同数据库中的集合。
* 如果输出集合不存在，则会创建一个新集合。
* 可以将结果（插入新文档、合并文档、替换文档、保留现有文档、操作失败、使用自定义更新管道处理文档）合并到现有集合中。
* 可以输出到分片的集合中。输入集合也可以是分片集合。

参考[`$merge`](https://docs.mongodb.com/manual/reference/operator/aggregation/merge/#mongodb-pipeline-pipe.-merge)：

* 有关[`$merge`](https://docs.mongodb.com/manual/reference/operator/aggregation/merge/#mongodb-pipeline-pipe.-merge)和可用选项的更多信息
* 示例：[按需物化视图：初始创建](https://docs.mongodb.com/manual/reference/operator/aggregation/merge/#std-label-merge-mat-view-init-creation)
* 示例：[按需物化视图：更新/替换数据](https://docs.mongodb.com/manual/reference/operator/aggregation/merge/#std-label-merge-mat-view-refresh)
* 示例：[仅插入新数据](https://docs.mongodb.com/manual/reference/operator/aggregation/merge/#std-label-merge-mat-view-insert-only)

原文链接：<https://docs.mongodb.com/manual/core/materialized-views/>

译者：李正洋


# 封顶集合

本文索引

* [概述](#概述)
* [表现](#表现)
* [限制与推荐](#限制与推荐)
* [使用](#使用)

## 概述

封顶集合 [capped collection](https://docs.mongodb.com/manual/reference/glossary/#term-capped-collection) 是固定大小的集合, 支持高吞吐的插入操作和根据插入顺序的查询操作. 封顶集合的工作方式与循环缓冲区 (circular buffers) 类似: 当一个集合填满了被分配的空间, 则通过覆盖最早的文档来为新的文档腾出空间.

参阅 [`createCollection()`](https://docs.mongodb.com/manual/reference/method/db.createCollection/#db.createCollection) 或 [`create`](https://docs.mongodb.com/manual/reference/command/create/#dbcmd.create) 获取更多创建封顶集合的信息.

## 表现

### 顺序插入

封顶集合保证了插入的顺序. 因此, 历史查询不需要索引排序. 没有这种索引开销, 封顶集合可以支持更高的插入吞吐量.

### 自动删除最早的文档

为了给新的文档腾出空间, 封顶集合会自动删除集合中最早的文档, 不需要定时脚本或者显示的删除操作.

例如, 在 [oplog.rs](https://docs.mongodb.com/manual/reference/glossary/#term-oplog) 集合中存储了 [replica set](https://docs.mongodb.com/manual/reference/glossary/#term-replica-set) 的操作的日志, 该集合就使用的是封顶集合. 除此之外, 还可以考虑以下潜在的用例:

* 存储由高容量 (high-volume) 系统生成的日志信息. 在封顶集合中不用索引插入文档的速度接近直接输出日志到文件系统. 而且, 内置的 *先进先出* 的属性维护了事件的顺序, 这在管理存储时用得到 (译注: 有些日志存储系统的顺序可能会乱, 如 Elasticsearch).
* 在封顶集合中记性数据缓存 (少量的). 由于缓存是高频读很少写, 因此你需要确保集合 *始终* 保留在工作区间 (即 RAM 中) *或者* 接受一些使用索引带来的写入的成本 (or accept some write penalty for the required index or indexes

  ).

### `_id` 索引

封顶集合有 `_id` 字段并且有一个基于 `_id` 字段的默认索引.

## 限制与推荐

### 更新

如果您计划更新封顶集合中的文档, 请创建一个索引, 来避免更新操进行集合扫描.

### 文档大小

在 3.2 版本中修改.

更新或替换文档大小的操作会失败. (注: 之前的 MMAPv1 可以修改)

### 文档删除

你不能删除封顶集合中的文档. 要删除集合中的所有文档, 请使用 [`drop()`](https://docs.mongodb.com/manual/reference/method/db.collection.drop/#db.collection.drop) 方法删除集合, 并重新创建封顶的集合.

### 分片

你不能对封顶集合进行分片操作.

### 查询效率

使用自然顺序 (natural ordering) 来有效地检索集合最近插入的元素. 这 (有点) 类似 `tail` 一个日志文件 (查看他的尾部).

### 聚合 `$out`

聚合管道操作符 [`$out`](https://docs.mongodb.com/manual/reference/operator/aggregation/out/#pipe._S_out)不能将结果写入封顶集合.

## 使用

### 创建封顶集合

When creating a capped collection you must specify the maximum size of the collection in bytes, which MongoDB will pre-allocate for the collection. The size of the capped collection includes a small amount of space for internal overhead.

您必须使用 [`db.createCollection()`](https://docs.mongodb.com/manual/reference/method/db.createCollection/#db.createCollection) 方法显式地创建封顶集合, 该过程可以通过 [`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo) shell 来帮忙执行 [`create`](https://docs.mongodb.com/manual/reference/command/create/#dbcmd.create) 命令. 在创建封顶集合时, 您必须预先指定集合的最大容量 (以字节为单位). 其中包括少量的内部空间.

```
db.createCollection( "log", { capped: true, size: 100000 } )
```

如果 `size` 字段小于或等于 4096, 则该集合将具有 4096 字节的容量. 此外, MongoDB 会提升用户所提供给的 size 大小直到其满足 256 的倍数为止.

Additionally, you may also specify a maximum number of documents for the collection using the`max`field as in the following document:

```
db.createCollection("log", { capped : true, size : 5242880, max : 5000 } )
```

> IMPORTANT
>
> The`size`argument is\_always\_required, even when you specify`max`number of documents. MongoDB will remove older documents if a collection reaches the maximum size limit before it reaches the maximum document count.

SEE

[`db.createCollection()`](https://docs.mongodb.com/manual/reference/method/db.createCollection/#db.createCollection)and[`create`](https://docs.mongodb.com/manual/reference/command/create/#dbcmd.create).

### 封顶集合查询

If you perform a[`find()`](https://docs.mongodb.com/manual/reference/method/db.collection.find/#db.collection.find)on a capped collection with no ordering specified, MongoDB guarantees that the ordering of results is the same as the insertion order.

To retrieve documents in reverse insertion order, issue[`find()`](https://docs.mongodb.com/manual/reference/method/db.collection.find/#db.collection.find)along with the[`sort()`](https://docs.mongodb.com/manual/reference/method/cursor.sort/#cursor.sort)method with the[`$natural`](https://docs.mongodb.com/manual/reference/operator/meta/natural/#metaOp._S_natural)parameter set to`-1`, as shown in the following example:

```
db.cappedCollection.find().sort( { $natural: -1 } )
```

### 检查集合是否封顶

Use the[`isCapped()`](https://docs.mongodb.com/manual/reference/method/db.collection.isCapped/#db.collection.isCapped)method to determine if a collection is capped, as follows:

```
db.collection.isCapped()
```

### 集合转换为固定大小集合

You can convert a non-capped collection to a capped collection with the[`convertToCapped`](https://docs.mongodb.com/manual/reference/command/convertToCapped/#dbcmd.convertToCapped)command:

```
db.runCommand({"convertToCapped": "mycoll", size: 100000});
```

The`size`parameter specifies the size of the capped collection in bytes.

> WARNING
>
> This command obtains a global write lock and will block other operations until it has completed.

### Automatically Remove Data After a Specified Period of Time

As an alternative to 封顶集合, consider MongoDB’s[TTL](https://docs.mongodb.com/manual/reference/glossary/#term-ttl)(“*time to live*”) indexes. As described in[Expire Data from Collections by Setting TTL](https://docs.mongodb.com/manual/tutorial/expire-data/), these indexes allow you to expire and remove data from normal collections based on the value of a date-typed field and a TTL value for the index.

> IMPORTANT
>
> [TTL indexes](https://docs.mongodb.com/manual/tutorial/expire-data/)are not compatible with 封顶集合.

### Tailable Cursor

You can use a[tailable cursor](https://docs.mongodb.com/manual/reference/glossary/#term-tailable-cursor)with 封顶集合. Similar to the Unix`tail-f`command, the tailable cursor “tails” the end of a capped collection. As new documents are inserted into the capped collection, you can use the tailable cursor to continue retrieving documents.

See[Tailable Cursors](https://docs.mongodb.com/manual/core/tailable-cursors/)for information on creating a tailable cursor.

原文链接：<https://docs.mongodb.com/v4.2/core/capped-collections/>


# 时间序列集合

## Time-Series Collections

## 时间序列集合

## Glossary 名词解释

**bucket**：带有相同的元数据且在一段有限制的间隔区间内的测量值组。

**bucket collection** ： 用于存储时序型集合的底层的分组桶的系统集合。复制、分片和索引都是在桶级别上完成的。

**measurement**：带有特定时间序列的K-V集合。

**meta-data**：时序序列里很少随时间变化的K-V对，同时可以用于识别整个时序序列。

**time-series**：一段间隔内的一系列测量值。

**time-series collection**：一种表示可写的非物化的视图的集合类型，它允许存储和查询多个时间序列，每个序列可以有不同的元数据。

MongoDB在5.0中支持了新的`timeseries collection`类型的选项，该类型用于存储时序型数据。`timeseries collection`提供了一组用于插入和查询测量值的简单接口，同时底层实际的数据是存储在以`bucket`形式的集合中。

在创建`timeseries collection`时，`timeField`字段是最小必备的配置项。`metaField`是另一个可选的、可被指定的元数据字段，它是用于在`bucket`中对测量值分组的依据。MongoDB通过提供`expireAfterSeconds`字段选项，也支持了对测量值的过期机制。

在`mydb`数据库中有个以`mytscoll` 命名的`timeseries collection`，该集合在MongoDB内部的`catelog`(用于存储集合或视图的信息)里是由一个视图和一个系统集合组成的。

* `mydb.mytscoll` 是个视图，它在MongoDB底层是用`bucket collection`作为包含特定属性的原始集合实现的：
  * 该视图是可写的（仅支持插入）。同时每个被插入的文档必须包含时间字段。
  * 在查询视图时，它会隐式地展开底层在`bucket collection`中存储的数据，然后返回原始的非`bucket`形式的文档数据。
    * 该视图就是通过`aggregation`里的`$_internalUnpackBucket`来实现展开`bucket`里数据的。
* 该系统集合的命名空间是`mydb.system.buckets.mytscoll`，它是用来存储实际数据的。
  * 每一个在`bucket collection`里的文档，都表示了一组区间间隔的时序型数据。
  * 如果在创建`timeseries collection`时，定义了`metaField`元数据字段，那么所有在`bucket`里的测量值都会有这个通用的元数据字段。
  * 除了时间范围，`bucket`还限制了每个文档数据的总条数以及测量值的大小。

### Bucket Collection Schema

```
{
    _id: <Object ID with time component equal to control.min.<time field>>,
    control: {
        // <Some statistics on the measurements such min/max values of data fields>
        version: 1,  // Version of bucket schema. Currently fixed at 1 since this is the
                     // first iteration of time-series collections.
        min: {
            <time field>: <time of first measurement in this bucket, rounded down based on granularity>,
            <field0>: <minimum value of 'field0' across all measurements>,
            <field1>: <maximum value of 'field1' across all measurements>,
            ...
        },
        max: {
            <time field>: <time of last measurement in this bucket>,
            <field0>: <maximum value of 'field0' across all measurements>,
            <field1>: <maximum value of 'field1' across all measurements>,
            ...
        },
        closed: <bool> // Optional, signals the database that this document will not receive any
                       // additional measurements.
    },
    meta: <meta-data field (if specified at creation) value common to all measurements in this bucket>,
    data: {
        <time field>: {
            '0', <time of first measurement>,
            '1', <time of second measurement>,
            ...
            '<n-1>': <time of n-th measurement>,
        },
        <field0>: {
            '0', <value of 'field0' in first measurement>,
            '1', <value of 'field0' in first measurement>,
            ...
        },
        <field1>: {
            '0', <value of 'field1' in first measurement>,
            '1', <value of 'field1' in first measurement>,
            ...
        },
        ...
    }
}
```

### Indexes 索引

为了保证`timeseries collection`的查询可以受益于索引扫描而不是全表扫描，`timeseries collection`允许索引可以被创建在时间上，元数据上以及元数据的子属性上。从MongoDB 5.2开始，在`timeseries collection`也允许索引被创建在测量值上。用户使用`createIndex`命令提供的索引规范被转换为底层`buckets collection`的模式。

* `timeseries collection`与底层的`buckets collection`之间的索引映射转换关系细节，可以参考[timeseries\_index\_schema\_conversion\_functions.h](https://github.com/mongodb/mongo/blob/master/src/mongo/db/timeseries/timeseries_index_schema_conversion_functions.h).
* 在v5.2及以上版本的最新支持的索引类型，`timeseries collection`会存储用户原始的索引定义到变换后的索引定义上。当从底层的`bucket collection`的索引映射到`timeseries collections`的索引时，会返回用户原始的索引定义。

当索引被创建后，可以通过`listIndexes`命令或`$indexStats`聚合计划来检查。`listIndexes`和`$indexStats`是作用于`timeseries collections`的，执行时，它们会在内部将底层的`bucket collection`的索引转化成`timeseries`格式的索引，并返回。比如，当我们在元数据字段中定义有`mm`的`timeseries collection`上执行`listIndexes`命令时，底层的`bucket collection`的`{meta:1}`索引，将会以`{mm:1}`格式返回。

`dropIndex`和`collMod`(`hidden: <bool>`, `expireAfterSeconds: <num>`)也同样支持在`timeseries collection`上。

时间字段上支持的索引类型：

* [单字段索引](https://docs.mongodb.com/manual/core/index-single/)
* [组合索引](https://docs.mongodb.com/manual/core/index-compound/)
* [哈希索引](https://docs.mongodb.com/manual/core/index-hashed/)
* [通配符索引](https://docs.mongodb.com/manual/core/index-wildcard/)
* [稀疏索引](https://docs.mongodb.com/manual/core/index-sparse/)
* [多键索引](https://docs.mongodb.com/manual/core/index-multikey/)
* [带排序的索引](https://docs.mongodb.com/manual/indexes/#indexes-and-collation)

元数据字段和元数据子字段支持的索引类型：

* 支持所有时间字段上支持的索引类型
* v5.2及以上版本支持[2d](https://github.com/mongodb-china/MongoDB-CN-Manual/blob/master/mongo-introduction/databases-and-collections/\(https:/docs.mongodb.com/manual/core/2d/\)/README.md)索引
* v5.2及以上版本支持[2dsphere](https://github.com/mongodb-china/MongoDB-CN-Manual/blob/master/mongo-introduction/databases-and-collections/\(https:/docs.mongodb.com/manual/core/2dsphere/\)/README.md)索引
* v5.2及以上版本支持[Partial索引](https://docs.mongodb.com/manual/core/index-partial/)

仅在v5.2及以上版本，测量值字段支持的索引类型

* [单字段索引](https://docs.mongodb.com/manual/core/index-single/)
* [组合索引](https://docs.mongodb.com/manual/core/index-compound/)
* [2dsphere](https://docs.mongodb.com/manual/core/2dsphere/)
* [部分条件索引](https://docs.mongodb.com/manual/core/index-partial/)

`timeseries collections`上不支持的索引类型，包括[唯一索引](https://docs.mongodb.com/manual/core/index-unique/)以及[文本索引](https://docs.mongodb.com/manual/core/index-text/)

### BucketCatalog

为了保证高效地桶（分组）操作，我们在`BucketCatalog`里维护了一组开启的桶，可以在[bucket\_catalog.h](https://github.com/mongodb/mongo/blob/master/src/mongo/db/timeseries/bucket_catalog.h)找到。在更高的级别，我们尝试着把并发写程序的写操作分组合并为可以一起提交地批处理，以减少对底层文档的写次数。写程序会插入它的输入批处理里的每一个文档到`BucketCatalog`，然后`BucketCatalog`会返回一个`BucketCatalog::WriteBatch`的处理器。一旦完成上面那些插入操作后，写程序就会检查每个写批处理。如果没有其他的写程序已经对批处理声明提交的权利，那么它会声明权利，并会提交它的批处理。否则，写程序将会稍后再提交处理。当它检查完所有的批处理，写程序将会等待其他的写程序提交每个剩下的批处理。

在内部，`BucketCatalog`维护一组对每个`bucket`文档的更新操作。当批处理被提交时，它会将这些插入转换到成`buckets`的列格式，并确保任何`control`字段的更新（例如`control.min`和 `control.max`）

当`bucket`文档在没有通过`BucketCatalog`的情况下被更新时，写程序就需要为有问题的文档或命名空间去调用`BucketCatalog::clear`，这样它就可以更新它的内部状态，避免写入任何可能破坏`bucket`格式的数据。这通常由OP观察者处理，但可能需要通过其他地方去调用。

`bucket`既可以通过手动设置选项`control.closed` 标识来关闭，也可以在许多场景下通过 `BucketCatalog` 自动关闭。如果`BucketCatalog`使用了超出给定的阈值（可通过服务器参数`timeseriesIdleBucketExpiryMemoryUsageThreshold`控制）的更多内存，此时它将会开始去关闭空闲的`bucket`。如果`bucket`是开启的且它没有任何未处于等待中未提交的测量值时，那么它就会被视为空闲的`bucket`。在下面这些场景下 `BucketCatalog` 也会关闭`bucket`: 如果它拥有超过最大阈值（`timeseriesBucketMaxCount`）的测量值数据的数量；如果它拥有过大的数据量大小（`timeseriesBucketMaxSize`）；又或者一个新的测量值数据是否是会导致`bucket`在其最旧的时间戳和最新的时间戳之间跨度比允许的间隔更长的时间（当前硬编码为一小时）。如果传入的测量值在原理上与已经到达给定`bucket`的度量不兼容，该`bucket`将被关闭，同时可以使用`numBucketsClosedDueToSchemaChange`度量进行跟踪。

在第一次提交给定`bucket`的写批处理时，就会生成新的完整的文档。后续的批处理提交中，我们只执行更新操作，不再生成新的完整的文档（因此称为‘经典’更新），是直接创建`DocDiff` （“delta”或者v2的更新）

## Granularity 粒度（时间间隔单位）

`timeseries collection`的`granularity`选项在集合创建的时候，可以被设置成`seconds`，`minutes`或者`hours`。后期可通过`colMod`操作来修改这个选项从`seconds`到`minutes`或者从`minutes`到`hours`，除此之外的转化修改目前都是不支持的。该参数想要表示在已给定的时序型测量数据之间的粗略的时间间隔，同时也用于调节其他内部参数对分组的影响。

单个`bucket`被允许的最大时间跨度，是由`granularity`选项控制，对于`seconds`，最大的时间跨度被设置成1小时，对于`minutes`就是24小时，对于`hours`就是30天。

当通过`BucketCatalog`开启新的`bucket`时，`_id`里的时间戳就是等同于`control.min.<time field>`的值，该值是从第一个插入bucket的测量数据中根据`granularity`选项来向下近似舍入而得到的。对于`seconds`，它将向下舍入到最接近的分钟，对于`minutes`，将向下舍入到最接近的小时，对于`hours`，它将向下舍入到最接近的日期。在闰秒和日历中的其他不规则情况下，这种舍入可能并不完美，并且通常通过对自纪元以来的秒数进行基本模运算来完成，假设每分钟60秒，每小时60分钟，以及每天24小时。

## Updates and Deletes

`timeseries collection`支持符合以下限制的删除语句

* 仅支持`metaField`的属性的查询语句
* 支持批量操作

同时更新满足上面同样的条件，另外遵循：

* 仅支持`metaField`对应的属性值
* 更新操作指定一个带有更新运算符表达式的更新文档（而不是替换文档或者更新的pipeline操作）
* 不支持`upsert:true`操作

这些更新与删除的执行都会被转换成相对应的底层的`bucket collection`的更新或删除操作。特别是，对于查询和更新文档，我们会使用真正的字段`meta`替换集合的`metaField`。（参见[Bucket集合规范](https://github.com/mongodb/mongo/blob/master/src/mongo/db/timeseries/README.md#bucket-collection-schema)）

例如，对于一个使用`metaField: "tag"`创建的`timeseries`集合`db.ts`，考虑一个对这个集合的更新操作，其查询语句是`{"tag.tag.a": "a"}`，同时更新文档语句是`{$set: {"tag.tag.a": "A"}, $rename: {"tag.tag.b": "tag.tag.c"}}`。这个更新操作在`db.system.buckets.ts`上会被转换成，查询语句是`{"meta.tag.a": "a"}`，更新语句是`{$set: {"meta.tag.a": "A"}, $rename: {"meta.tag.b": "meta.tag.c"}}`。然后这个转换后的更新语句就可以像普通的更新操作一样执行。上面这些转换流程也适用于删除操作。

## References 参考文献

See: [MongoDB Blog: Time Series Data and MongoDB: Part 2 - Schema Design Best Practices](https://www.mongodb.com/blog/post/time-series-data-and-mongodb-part-2-schema-design-best-practices)


# 文档

在本页面

* [文档结构](https://docs.mongodb.com/v4.2/core/document/#document-structure)
* [点符号](https://docs.mongodb.com/v4.2/core/document/#dot-notation)
* [文档限制](https://docs.mongodb.com/v4.2/core/document/#document-limitations)
* [文档结构的其他用途](https://docs.mongodb.com/v4.2/core/document/#other-uses-of-the-document-structure)
* [更多阅读](https://docs.mongodb.com/v4.2/core/document/#further-reading)

MongoDB将数据记录存储为BSON文档。BSON是[JSON](https://docs.mongodb.com/v4.2/reference/glossary/#term-json)文档的二进制表示[形式](https://docs.mongodb.com/v4.2/reference/glossary/#term-json)，尽管它包含比JSON更多的数据类型。有关BSON规范，请参见[bsonspec.org](http://bsonspec.org/)。另请参阅[BSON类型](https://docs.mongodb.com/v4.2/reference/bson-types/)。

![A MongoDB document.](https://docs.mongodb.com/v4.2/_images/crud-annotated-document.bakedsvg.svg)

## 文档结构

MongoDB文档由字段和值对组成，并具有以下结构：

复制

```
{
   field1: value1,
   field2: value2,
   field3: value3,
   ...
   fieldN: valueN
}
```

字段的值可以是任何BSON [数据类型](https://docs.mongodb.com/v4.2/reference/bson-types/)，包括其他文档，数组和文档数组。例如，以下文档包含各种类型的值：

复制

```
var mydoc = {
               _id: ObjectId("5099803df3f4948bd2f98391"),
               name: { first: "Alan", last: "Turing" },
               birth: new Date('Jun 23, 1912'),
               death: new Date('Jun 07, 1954'),
               contribs: [ "Turing machine", "Turing test", "Turingery" ],
               views : NumberLong(1250000)
            }
```

上面的字段具有以下数据类型：

* `_id`拥有一个[ObjectId](https://docs.mongodb.com/v4.2/reference/bson-types/#objectid)。
* `name`包含一个包含字段`first`和`last`的\_嵌入式文档\_。
* `birth`和`death`保留\_Date\_类型的值。
* `contribs`拥有\_字符串数组\_。
* `views`拥有\_NumberLong\_类型的值。

### 字段名称

字段名称是字符串。

[文档](https://docs.mongodb.com/v4.2/core/document/#)对字段名称有以下限制：

* 字段名称`_id`保留用作主键；它的值在集合中必须是唯一的，不可变的，并且可以是数组以外的任何类型。
* 字段名称**不能**包含`null`字符。
* 顶级字段名称**不能**以美元符号（`$`）字符开头。

  否则，从MongoDB 3.6开始，服务器允许存储包含点（即`.`）和美元符号（即 `$`）的字段名称。

重要

MongoDB查询语言不能总是有效地表达对字段名称包含这些字符的文档的查询（请参阅[SERVER-30575](https://jira.mongodb.org/browse/SERVER-30575)）。

在查询语句中添加支持之前，不推荐在字段名称中使用`$`和 `.`，官方MongoDB的驱动程序不支持。

BSON文档可能有多个具有相同名称的字段。但是，大多数[MongoDB接口](https://docs.mongodb.com/ecosystem/drivers)都使用不支持重复字段名称的结构（例如，哈希表）来表示MongoDB。如果需要处理具有多个同名字段的[文档](https://docs.mongodb.com/ecosystem/drivers)，请参见[驱动程序文档](https://docs.mongodb.com/ecosystem/drivers)。

内部MongoDB流程创建的某些文档可能具有重复的字段，但是\_任何\_ MongoDB流程都\_不会\_向现有的用户文档添加重复的字段。

### 字段值限制

* MongoDB 2.6至MongoDB版本，[并将featureCompatibilityVersion](https://docs.mongodb.com/v4.2/reference/command/setFeatureCompatibilityVersion/#view-fcv)（[fCV](https://docs.mongodb.com/v4.2/reference/command/setFeatureCompatibilityVersion/#view-fcv)）设置为`"4.0"`或更早版本

  对于[索引集合](https://docs.mongodb.com/v4.2/indexes/)，索引字段的值有一个最大索引键长度限制。有关详细信息，请参见[`Maximum Index Key Length`](https://docs.mongodb.com/v4.2/reference/limits/#Index-Key-Limit)。

## 点符号

MongoDB使用\_点符号\_访问数组的元素并访问嵌入式文档的字段。

### 数组

要通过从零开始的索引位置指定或访问数组的元素，请将数组名称与点（`.`）和从零开始的索引位置连接起来，并用引号引起来：

复制

```
"<array>.<index>"
```

例如，给定文档中的以下字段：

复制

```
{
   ...
   contribs: [ "Turing machine", "Turing test", "Turingery" ],
   ...
}
```

要指定`contribs`数组中的第三个元素，请使用点符号`"contribs.2"`。

有关查询数组的示例，请参见：

* [查询数组](https://docs.mongodb.com/v4.2/tutorial/query-arrays/)
* [查询嵌入式文档数组](https://docs.mongodb.com/v4.2/tutorial/query-array-of-documents/)

也可以看看

* `$[\]`用于更新操作的所有位置运算符，
* `$[/<identifier/>]` 过滤后的位置运算符，用于更新操作，
* [`$`](https://docs.mongodb.com/v4.2/reference/operator/update/positional/#up._S_) 用于更新操作的位置运算符，
* [`$`](https://docs.mongodb.com/v4.2/reference/operator/projection/positional/#proj._S_) 数组索引位置未知时的投影运算符
* [在数组中查询带数组](https://docs.mongodb.com/v4.2/tutorial/query-arrays/#read-operations-arrays)的点符号示例。

### 嵌入式文档

要使用点符号指定或访问嵌入式文档的字段，请将嵌入式文档名称与点（`.`）和字段名称连接在一起，并用引号引起来：

复制

```
"<embedded document>.<field>"
```

例如，给定文档中的以下字段：

复制

```
{
   ...
   name: { first: "Alan", last: "Turing" },
   contact: { phone: { type: "cell", number: "111-222-3333" } },
   ...
}
```

* 要指定在字段中命名`last`的`name`字段，请使用点符号`"name.last"`。
* 要在字段`number`中的`phone`文档中 指定`contact`，请使用点号`"contact.phone.number"`。

有关查询嵌入式文档的示例，请参见：

* [查询嵌入/嵌套文档](https://docs.mongodb.com/v4.2/tutorial/query-embedded-documents/)
* [查询嵌入式文档数组](https://docs.mongodb.com/v4.2/tutorial/query-array-of-documents/)

## 文件限制[¶](https://docs.mongodb.com/v4.2/core/document/#document-limitations)

文档具有以下属性：

### 文档大小限制

BSON文档的最大大小为16 MB。

最大文档大小有助于确保单个文档不会使用过多的RAM或在传输过程中占用过多的带宽。要存储大于最大大小的文档，MongoDB提供了GridFS API。有关GridFS的更多信息，请参见[`mongofiles`](https://docs.mongodb.com/v4.2/reference/program/mongofiles/#bin.mongofiles)和[驱动程序](https://docs.mongodb.com/ecosystem/drivers)的文档。

### 文档字段顺序

*除\_以下情况\_外*，MongoDB会在执行写操作后保留文档字段的顺序：

* 该`_id`字段始终是文档中的第一个字段。
* 包含[`renaming`](https://docs.mongodb.com/v4.2/reference/operator/update/rename/#up._S_rename)字段名称的更新可能会导致文档中字段的重新排序。

### `_id`字段

在MongoDB中，存储在集合中的每个文档都需要一个唯一的 [\_id](https://docs.mongodb.com/v4.2/reference/glossary/#term-id)字段作为[主键](https://docs.mongodb.com/v4.2/reference/glossary/#term-primary-key)。如果插入的文档省略了该`_id`字段，则MongoDB驱动程序会自动为该`_id`字段生成一个[ObjectId](https://docs.mongodb.com/v4.2/reference/bson-types/#objectid)。

这也适用于通过使用[upsert：true](https://docs.mongodb.com/v4.2/reference/method/db.collection.update/#upsert-parameter)更新操作插入的文档。

该`_id`字段具有以下行为和约束：

* 默认情况下，MongoDB 在创建集合期间会在`_id`字段上创建唯一索引。
* 该`_id`字段始终是文档中的第一个字段。如果服务器首先接收到没有该`_id`字段的文档，则服务器会将字段移到开头。
* 该`_id`字段可以包含除数组之外的任何[BSON数据类型的](https://docs.mongodb.com/v4.2/reference/bson-types/)值。

警告

为确保复制正常进行，请勿在`_id` 字段中存储BSON正则表达式类型的值。

以下是用于存储值的常用选项`_id`：

* 使用一个[ObjectId](https://docs.mongodb.com/v4.2/reference/bson-types/#objectid)。
* 使用自然的唯一标识符（如果有）。这样可以节省空间并避免附加索引。
* 生成一个自动递增的数字。
* 在您的应用程序代码中生成一个UUID。为了在集合和`_id` 索引中更有效地存储UUID值，请将UUID存储为BSON `BinData`类型的值。

  在以下情况下，`BinData`更有效地将类型为索引的键存储在索引中：

  * 二进制子类型的值在0-7或128-135的范围内，并且
  * 字节数组的长度为：0、1、2、3、4、5、6、7、8、10、12、14、16、20、24或32。
* 使用驱动程序的BSON UUID工具生成UUID。请注意，驱动程序实现可能会以不同的方式实现UUID序列化和反序列化逻辑，这可能与其他驱动程序不完全兼容。有关UUID互操作性的信息，请参阅[驱动程序文档](https://docs.mongodb.com/drivers/)。

注意

大多数MongoDB驱动程序客户端将包括该`_id`字段，并`ObjectId`在将插入操作发送到MongoDB之前生成一个；但是，如果客户发送的文档中没有`_id` 字段，则[`mongod`](https://docs.mongodb.com/v4.2/reference/program/mongod/#bin.mongod)会添加该`_id`字段并生成`ObjectId`。

## 文档结构的其他用途

除了定义数据记录外，MongoDB还在整个文档结构中使用，包括但不限于：[查询过滤器](https://docs.mongodb.com/v4.2/core/document/#document-query-filter)，[更新规范文档](https://docs.mongodb.com/v4.2/core/document/#document-update-specification)和[索引规范文档](https://docs.mongodb.com/v4.2/core/document/#document-index-specification)。

### 查询过滤器文档

查询过滤器文档指定确定用于选择哪些记录以进行读取，更新和删除操作的条件。

您可以使用 `<field>:<value>` 表达式指定相等条件和[查询运算符](https://docs.mongodb.com/v4.2/reference/operator/query/) 表达式。

复制

```
{
  <field1>: <value1>,
  <field2>: { <operator>: <value> },
  ...
}
```

有关示例，请参见：

* [查询文档](https://docs.mongodb.com/v4.2/tutorial/query-documents/)
* [查询嵌入/嵌套文档](https://docs.mongodb.com/v4.2/tutorial/query-embedded-documents/)
* [查询数组](https://docs.mongodb.com/v4.2/tutorial/query-arrays/)
* [查询嵌入式文档数组](https://docs.mongodb.com/v4.2/tutorial/query-array-of-documents/)

### 更新规范文档

更新规范文档使用[更新运算符](https://docs.mongodb.com/v4.2/reference/operator/update/#id1)来指定要在[`db.collection.update()`](https://docs.mongodb.com/v4.2/reference/method/db.collection.update/#db.collection.update)操作期间在特定字段上执行的数据修改。

复制

```
{
  <operator1>: { <field1>: <value1>, ... },
  <operator2>: { <field2>: <value2>, ... },
  ...
}
```

有关示例，请参阅[更新规范](https://docs.mongodb.com/v4.2/tutorial/update-documents/#update-documents-modifiers)。

### 索引规范文档

索引规范文档定义了要索引的字段和索引类型：

复制

```
{ <field1>: <type1>, <field2>: <type2>, ...  }
```

## 进一步阅读

有关MongoDB文档模型的更多信息，请下载 [MongoDB应用程序现代化指南](https://www.mongodb.com/modernize?tck=docs_server)。

下载内容包括以下资源：

* 演示使用MongoDB进行数据建模的方法
* 白皮书涵盖了从[RDBMS](https://docs.mongodb.com/v4.2/reference/glossary/#term-rdbms)数据模型迁移到MongoDB的最佳实践和注意事项
* 参考MongoDB模式及其等效RDBMS
* 应用程序现代化记分卡

原文链接：<https://docs.mongodb.com/v4.2/core/document/>

译者：小芒果


# BSON类型

在本页面

* [对象Id ObjectId](https://docs.mongodb.com/v4.2/reference/bson-types/#objectid)
* [字符串 String](https://docs.mongodb.com/v4.2/reference/bson-types/#string)
* [时间戳 Timestamps](https://docs.mongodb.com/v4.2/reference/bson-types/#timestamps)
* [日期 Date](https://docs.mongodb.com/v4.2/reference/bson-types/#date)

[BSON](https://docs.mongodb.com/v4.2/reference/glossary/#term-bson)是一种二进制序列化格式，用于在MongoDB中存储文档和进行远程过程调用。BSON规范位于[ bsonspec.org](http://bsonspec.org/)。

每种BSON类型都具有整数和字符串标识符，如下表所示：

| 类型 Type                 | 对应数字 Number | 别名 Alias              | 备注 Notes  |
| ----------------------- | ----------- | --------------------- | --------- |
| 双精度浮点型Double            | 1           | “double”              |           |
| 字符串String               | 2           | “string”              |           |
| 对象Object                | 3           | “object”              |           |
| 数组Array                 | 4           | “array”               |           |
| 二进制数据Binary data        | 5           | “binData”             |           |
| 未定义Undefined            | 6           | “undefined”           | 不推荐使用。    |
| 对象编号ObjectId            | 7           | “objectId”            |           |
| 布尔型Boolean              | 8           | “bool”                |           |
| 日期Date                  | 9           | “date”                |           |
| 空值Null                  | 10          | “null”                |           |
| 正则表达式Regular Expression | 11          | “regex”               |           |
| DBPointer               | 12          | “dbPointer”           | 不推荐使用。    |
| JavaScript              | 13          | “javascript”          |           |
| Symbol                  | 14          | “symbol”              | 不推荐使用。    |
| JavaScript (带范围)        | 15          | “javascriptWithScope” |           |
| 32位整数 32-bit integer    | 16          | “int”                 |           |
| 时间戳 Timestamp           | 17          | “timestamp”           |           |
| 64位整数 64-bit integer    | 18          | “long”                |           |
| 小数128 Decimal128        | 19          | “decimal”             | 3.4版的新功能。 |
| 最小键 Min key             | -1          | “minKey”              |           |
| 最大键 Max key             | 127         | “maxKey”              |           |

您可以将这些值与[`$type`](https://docs.mongodb.com/v4.2/reference/operator/query/type/#op._S_type)运算符一起使用，以按其BSON类型查询文档。所述[`$type`](https://docs.mongodb.com/v4.2/reference/operator/aggregation/type/#exp._S_type)聚合操作者返回的类型[操作者表达](https://docs.mongodb.com/v4.2/meta/aggregation-quick-reference/#agg-quick-ref-operator-expressions)使用列出的BSON类型字符串之一。

要确定字段的类型，请参阅[mongo Shell中的Check Types](https://docs.mongodb.com/v4.2/core/shell-types/#check-types-in-shell)。

如果将BSON转换为JSON，请参阅[扩展JSON](https://docs.mongodb.com/v4.2/reference/mongodb-extended-json/)参考。

以下各节描述了特定BSON类型的特殊注意事项。

## ObjectId

ObjectId很小，可能唯一，可以快速生成并排序。ObjectId值的长度为12个字节，包括：

* 一个4字节的\_时间戳记值\_，代表自Unix时代以来以秒为单位的ObjectId的创建
* 5字节\_随机值\_
* 3字节\_递增计数器\_，初始化为随机值

虽然BSON格式本身是低位优先的，但\_时间戳\_和 \_计数器\_值却是高位优先的，最高有效字节在字节序列中排在最前面。

在MongoDB中，存储在集合中的每个文档都需要一个唯一的 [\_id](https://docs.mongodb.com/v4.2/reference/glossary/#term-id)字段作为[主键](https://docs.mongodb.com/v4.2/reference/glossary/#term-primary-key)。如果插入的文档省略了该`_id`字段，则MongoDB驱动程序会自动为该字段生成一个[ObjectId](https://docs.mongodb.com/v4.2/reference/bson-types/#objectid)`_id`。

这也适用于通过[upsert：true](https://docs.mongodb.com/v4.2/reference/method/db.collection.update/#upsert-parameter)通过更新操作插入的文档。

MongoDB客户端应添加一个`_id`具有唯一ObjectId 的字段。在该`_id`字段中使用ObjectIds 还可以带来以下好处：

* 在[`mongo`](https://docs.mongodb.com/v4.2/reference/program/mongo/#bin.mongo)shell中，您可以使用[`ObjectId.getTimestamp()`](https://docs.mongodb.com/v4.2/reference/method/ObjectId.getTimestamp/#ObjectId.getTimestamp)方法访问`ObjectId`的创建时间。
* 在存储`ObjectId`值的`_id`字段上按大致相当于创建时间进行排序。

  重要

  尽管[ObjectId](https://docs.mongodb.com/v4.2/reference/bson-types/#objectid)值应随时间增加，但不一定是单调的。这是因为他们：

  * 仅包含一秒的时间分辨率，因此 在同一秒内创建的[ObjectId](https://docs.mongodb.com/v4.2/reference/bson-types/#objectid)值没有保证的顺序，并且
  * 由客户端生成，客户端可能具有不同的系统时钟。

也可以看看

[`ObjectId()`](https://docs.mongodb.com/v4.2/reference/method/ObjectId/#ObjectId)

## 字符串

BSON字符串为UTF-8。通常，在对BSON进行序列化和反序列化时，每种编程语言的驱动程序都会从该语言的字符串格式转换为UTF-8。这样就可以轻松地将大多数国际字符存储在BSON字符串中。 [\[1\]](https://docs.mongodb.com/v4.2/reference/bson-types/#sort-string-internationalization)此外，MongoDB [`$regex`](https://docs.mongodb.com/v4.2/reference/operator/query/regex/#op._S_regex)查询在正则表达式字符串中支持UTF-8。

|                                                                  |                                                                                                                                                                                                                                                      |
| ---------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [\[1\]](https://docs.mongodb.com/v4.2/reference/bson-types/#id3) | 给定使用UTF-8字符集的[`sort()`](https://docs.mongodb.com/v4.2/reference/method/cursor.sort/#cursor.sort)字符串，在字符串上使用将是合理正确的。但是，由于内部 [`sort()`](https://docs.mongodb.com/v4.2/reference/method/cursor.sort/#cursor.sort)使用C ++ `strcmp`API，因此排序顺序可能会错误地处理某些字符。 |
|                                                                  |                                                                                                                                                                                                                                                      |

## 时间戳

BSON有一个特殊的时间戳类型给MongoDB\_内部\_ 使用，而非常规相关的[日期](https://docs.mongodb.com/v4.2/reference/bson-types/#document-bson-type-date) 类型。此内部时间戳记类型是64位值，其中：

* 最重要的32位是一个`time_t`值（自Unix时代以来的秒数）
* 最低有效32位是`ordinal`给定秒内的操作增量。

虽然BSON格式是低位优先的，因此首先存储了最低有效位，但是无论字节序如何，在所有平台上[`mongod`](https://docs.mongodb.com/v4.2/reference/program/mongod/#bin.mongod)实例始终将`time_t`值与`ordinal`值比较。

在单个[`mongod`](https://docs.mongodb.com/v4.2/reference/program/mongod/#bin.mongod)实例中，时间戳记值始终是唯一的。

在复制中，操作[日志](https://docs.mongodb.com/v4.2/reference/glossary/#term-oplog)具有一个`ts`字段。该字段中的值反映了使用BSON时间戳值的操作时间。

注意

BSON时间戳类型供MongoDB\_内部\_ 使用。在大多数情况下，在应用程序开发中，您将需要使用BSON日期类型。有关更多信息，请参见[日期](https://docs.mongodb.com/v4.2/reference/bson-types/#document-bson-type-date)。

当插入包含带有空时间戳值的顶级字段的文档时，MongoDB会将空时间戳值替换为当前时间戳值，但以下情况除外。如果`_id` 字段本身包含空的时间戳记值，则将始终按原样插入而不替换它。

示例

插入带有空时间戳值的文档：

复制

```
db.test.insertOne( { ts: new Timestamp() } );
```

运行[`db.test.find()`](https://docs.mongodb.com/v4.2/reference/method/db.collection.find/#db.collection.find) 然后将返回类似于以下内容的文档：

```
{ "_id" : ObjectId("542c2b97bac0595474108b48"), "ts" : Timestamp(1412180887, 1) }
```

服务器已使用插入时的时间戳值替换了`ts`的空时间戳值。

## 日期 Date

BSON Date是一个64位整数，代表自Unix纪元（1970年1月1日）以来的毫秒数。这导致可以追溯到过去和未来约2.9亿年的日期范围。

该[官方BSON规范](http://bsonspec.org/#/specification) 指的是BSON Date类型为\_UTC日期时间\_。

BSON日期类型是有符号整数。[\[2\]](https://docs.mongodb.com/v4.2/reference/bson-types/#unsigned-date)负值表示1970年之前的日期。

示例

在 [`mongo`](https://docs.mongodb.com/v4.2/reference/program/mongo/#bin.mongo) shell中使用构造函数 `new Date()` 构造一个Date ：

复制

```
var mydate1 = new Date()
```

示例

在 [`mongo`](https://docs.mongodb.com/v4.2/reference/program/mongo/#bin.mongo) shell中使用构造函数`ISODate()`构造一个Date ：

复制

```
var mydate2 = ISODate()
```

示例

以字符串形式返回`Date`值：

复制

```
mydate1.toString()
```

示例

返回日期值的月份部分；月是零索引，因此一月是`0`月：

复制

```
mydate1.getMonth()
```

|                                                                  |                                                                                                                         |
| ---------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| [\[2\]](https://docs.mongodb.com/v4.2/reference/bson-types/#id4) | 在2.0版之前，`Date`值被错误地解释为\_无符号\_整数，这会影响排序，范围查询和`Date`字段索引。由于升级时不会重新创建索引，因此，如果您早期版本使用`Date`值创建了索引，请对与应用相关的、1970年前的日期进行重新索引。 |
|                                                                  |                                                                                                                         |

原文链接：<https://docs.mongodb.com/v4.2/reference/bson-types/>

译者：小芒果


# Comparison and Sort Order

On this page

* [Numeric Types](https://docs.mongodb.com/manual/reference/bson-type-comparison-order/#numeric-types)
* [Strings](https://docs.mongodb.com/manual/reference/bson-type-comparison-order/#strings)
* [Arrays](https://docs.mongodb.com/manual/reference/bson-type-comparison-order/#arrays)
* [Dates and Timestamps](https://docs.mongodb.com/manual/reference/bson-type-comparison-order/#dates-and-timestamps)
* [Non-existent Fields](https://docs.mongodb.com/manual/reference/bson-type-comparison-order/#non-existent-fields)
* [BinData](https://docs.mongodb.com/manual/reference/bson-type-comparison-order/#bindata)

When comparing values of different[BSON types](https://docs.mongodb.com/manual/reference/bson-types/#bson-types), MongoDB uses the following comparison order, from lowest to highest:

1. MinKey (internal type)
2. Null
3. Numbers (ints, longs, doubles, decimals)
4. Symbol, String
5. Object
6. Array
7. BinData
8. ObjectId
9. Boolean
10. Date
11. Timestamp
12. Regular Expression
13. MaxKey (internal type)

## Numeric Types

MongoDB treats some types as equivalent for comparison purposes. For instance, numeric types undergo conversion before comparison.

## Strings

### Binary Comparison

By default, MongoDB uses the simple binary comparison to compare strings.

### Collation

New in version 3.4.

[Collation](https://docs.mongodb.com/manual/reference/collation/)allows users to specify language-specific rules for string comparison, such as rules for lettercase and accent marks.

Collation specification has the following syntax:

```
{
locale
:
<
string
>
,
caseLevel
:
<
boolean
>
,
caseFirst
:
<
string
>
,
strength
:
<
int
>
,
numericOrdering
:
<
boolean
>
,
alternate
:
<
string
>
,
maxVariable
:
<
string
>
,
backwards
:
<
boolean
>
}
```

When specifying collation, the`locale`field is mandatory; all other collation fields are optional. For descriptions of the fields, see[Collation Document](https://docs.mongodb.com/manual/reference/collation/#collation-document-fields).

If no collation is specified for the collection or for the operations, MongoDB uses the simple binary comparison used in prior versions for string comparisons.

## Arrays

With arrays, a less-than comparison or an ascending sort compares the smallest element of arrays, and a greater-than comparison or a descending sort compares the largest element of the arrays. As such, when comparing a field whose value is a single-element array (e.g.`[1]`) with non-array fields (e.g.`2`), the comparison is between`1`and`2`. A comparison of an empty array (e.g.`[]`) treats the empty array as less than`null`or a missing field.

## Dates and Timestamps

Changed in version 3.0.0:Date objects sort before Timestamp objects. Previously Date and Timestamp objects sorted together.

## Non-existent Fields

The comparison treats a non-existent field as it would an empty BSON Object. As such, a sort on the`a`field in documents`{}`and`{a:null}`would treat the documents as equivalent in sort order.

## BinData

MongoDB sorts`BinData`in the following order:

1. First, the length or size of the data.
2. Then, by the BSON one-byte subtype.
3. Finally, by the data, performing a byte-by-byte comparison.


# MongoDB Extended JSON (v2)

On this page

* [Parsers and Supported Format](https://docs.mongodb.com/manual/reference/mongodb-extended-json/#parsers-and-supported-format)
* [BSON Data Types and Associated Representations](https://docs.mongodb.com/manual/reference/mongodb-extended-json/#bson-data-types-and-associated-representations)

[JSON](https://docs.mongodb.com/manual/reference/glossary/#term-json)can only represent a subset of the types supported by[BSON](https://docs.mongodb.com/manual/reference/glossary/#term-bson). To preserve type information, MongoDB adds the following extensions to the JSON format:

* *Strict mode*

  . Strict mode representations of BSON types conform to the

  [JSON RFC](http://www.json.org/)

  . Any JSON parser can parse these strict mode representations as key/value pairs; however, only the MongoDB internal JSON parser recognizes the type information conveyed by the format.
* `mongo`

  *Shell mode*

  . The MongoDB internal JSON parser and the

  [`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo)

  shell can parse this mode.

The representation used for the various data types depends on the context in which the JSON is parsed.

## Parsers and Supported Format

### Input in Strict Mode

The following can parse representations in strict mode\_with\_recognition of the type information.

* [REST Interfaces](https://docs.mongodb.com/ecosystem/tools/http-interfaces)
* [`mongoimport`](https://docs.mongodb.com/manual/reference/program/mongoimport/#bin.mongoimport)
* `--query`

  option of various MongoDB tools
* [MongoDB Compass](https://www.mongodb.com/products/compass)

Other JSON parsers, including[`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo)shell and[`db.eval()`](https://docs.mongodb.com/manual/reference/method/db.eval/#db.eval), can parse strict mode representations as key/value pairs, but\_without\_recognition of the type information.

### Input in`mongo`Shell Mode

The following can parse representations in`mongo`shell mode\_with\_recognition of the type information.

* [REST Interfaces](https://docs.mongodb.com/ecosystem/tools/http-interfaces)
* [`mongoimport`](https://docs.mongodb.com/manual/reference/program/mongoimport/#bin.mongoimport)
* `--query`

  option of various MongoDB tools
* [`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo)

  shell

### Output in Strict mode

[`mongoexport`](https://docs.mongodb.com/manual/reference/program/mongoexport/#bin.mongoexport)and[REST and HTTP Interfaces](https://docs.mongodb.com/ecosystem/tools/http-interfaces)output data in\_Strict mode\_.

### Output in`mongo`Shell Mode

[`bsondump`](https://docs.mongodb.com/manual/reference/program/bsondump/#bin.bsondump)outputs in`mongo`*Shell mode*.

## BSON Data Types and Associated Representations

The following presents the BSON data types and the associated representations in\_Strict mode\_and`mongo`\_Shell mode\_.

### Binary

`data_binary`

|                                              |                                                                               |                              |
| -------------------------------------------- | ----------------------------------------------------------------------------- | ---------------------------- |
| Strict Mode                                  | [`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo) | Shell Mode                   |
| { "$binary": "\<bindata>", "$type": "\<t>" } |                                                                               | BinData ( \<t>, \<bindata> ) |

* `<bindata>`is the base64 representation of a binary string.
* `<t>`is a representation of a single byte indicating the data type. In

  *Strict mode*

  it is a hexadecimal string, and in

  *Shell mode*

  it is an integer. See the extended bson documentation.

  <http://bsonspec.org/spec.html>

### Date

`data_date`

|                        |                                                                               |                      |
| ---------------------- | ----------------------------------------------------------------------------- | -------------------- |
| Strict Mode            | [`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo) | Shell Mode           |
| { "$date": "\<date>" } |                                                                               | new Date ( \<date> ) |

In\_Strict mode\_,`<date>`is an ISO-8601 date format with a mandatory time zone field following the template`YYYY-MM-DDTHH:mm:ss.mmm<+/-Offset>`.

The MongoDB JSON parser currently does not support loading ISO-8601 strings representing dates prior to the[Unix epoch](https://docs.mongodb.com/manual/reference/glossary/#term-unix-epoch). When formatting pre-epoch dates and dates past what your system’s`time_t`type can hold, the following format is used:

```
{ "$date" : { "$numberLong" : "
<
dateAsMilliseconds
>
" } }
```

In\_Shell mode\_,`<date>`is the JSON representation of a 64-bit signed integer giving the number of milliseconds since epoch UTC.

### Timestamp

`data_timestamp`

|                                            |                                                                               |                         |
| ------------------------------------------ | ----------------------------------------------------------------------------- | ----------------------- |
| Strict Mode                                | [`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo) | Shell Mode              |
| { "$timestamp": { "t": \<t>, "i": \<i> } } |                                                                               | Timestamp( \<t>, \<i> ) |

* `<`

  `t`

  `>`

  is the JSON representation of a 32-bit unsigned integer for seconds since epoch.
* `<`

  `i`

  `>`

  is a 32-bit unsigned integer for the increment.

### Regular Expression

`data_regex`

|                                                      |                                                                               |                        |
| ---------------------------------------------------- | ----------------------------------------------------------------------------- | ---------------------- |
| Strict Mode                                          | [`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo) | Shell Mode             |
| { "$regex": "\<sRegex>", "$options": "\<sOptions>" } |                                                                               | /\<jRegex>/\<jOptions> |

* `<`

  `sRegex`

  `>`

  is a string of valid JSON characters.
* `<`

  `jRegex`

  `>`

  is a string that may contain valid JSON characters and unescaped double quote (

  `"`

  ) characters, but may not contain unescaped forward slash (

  `/`

  ) characters.
* `<`

  `sOptions`

  `>`

  is a string containing the regex options represented by the letters of the alphabet.
* `<`

  `jOptions`

  `>`

  is a string that may contain only the characters ‘g’, ‘i’, ‘m’ and ‘s’ (added in v1.9). Because the

  `JavaScript`

  and

  `mongo`

  `Shell`

  representations support a limited range of options, any nonconforming options will be dropped when converting to this representation.

### OID

`data_oid`

|                     |                                                                               |                     |
| ------------------- | ----------------------------------------------------------------------------- | ------------------- |
| Strict Mode         | [`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo) | Shell Mode          |
| { "$oid": "\<id>" } |                                                                               | ObjectId( "\<id>" ) |

`<id>`is a 24-character hexadecimal string.

### DB Reference

`data_ref`

|                                       |                                                                               |                           |
| ------------------------------------- | ----------------------------------------------------------------------------- | ------------------------- |
| Strict Mode                           | [`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo) | Shell Mode                |
| { "$ref": "\<name>", "$id": "\<id>" } |                                                                               | DBRef("\<name>", "\<id>") |

* `<`

  `name`

  `>`

  is a string of valid JSON characters.
* `<`

  `id`

  `>`

  is any valid extended JSON type.

### Undefined Type

`data_undefined`

|                        |                                                                               |            |
| ---------------------- | ----------------------------------------------------------------------------- | ---------- |
| Strict Mode            | [`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo) | Shell Mode |
| { "$undefined": true } |                                                                               | undefined  |

The representation for the JavaScript/BSON undefined type.

You\_cannot\_use`undefined`in query documents. Consider the following document inserted into the`people`collection:

```javascript
db.people.insert( { name : "Sally", age : undefined } )
```

The following queries return an error:

```javascript
db.people.find( { age : undefined } )
db.people.find( { age : { $gte : undefined } } )
```

However, you can query for undefined values using[`$type`](https://docs.mongodb.com/manual/reference/operator/query/type/#op._S_type), as in:

```javascript
db.people.find( { age : { $type : 6 } } )
```

This query returns all documents for which the`age`field has value`undefined`.

### MinKey

`data_minkey`

|                  |                                                                               |            |
| ---------------- | ----------------------------------------------------------------------------- | ---------- |
| Strict Mode      | [`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo) | Shell Mode |
| { "$minKey": 1 } |                                                                               | MinKey     |

The representation of the MinKey BSON data type that compares lower than all other types. See[Comparison/Sort Order](https://docs.mongodb.com/manual/reference/bson-type-comparison-order/#faq-dev-compare-order-for-bson-types)for more information on comparison order for BSON types.

### MaxKey

`data_maxkey`

|                  |                                                                               |            |
| ---------------- | ----------------------------------------------------------------------------- | ---------- |
| Strict Mode      | [`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo) | Shell Mode |
| { "$maxKey": 1 } |                                                                               | MaxKey     |

The representation of the MaxKey BSON data type that compares higher than all other types. See[Comparison/Sort Order](https://docs.mongodb.com/manual/reference/bson-type-comparison-order/#faq-dev-compare-order-for-bson-types)for more information on comparison order for BSON types.

### NumberLong

New in version 2.6.

`data_numberlong`

|                                |                                                                               |                           |
| ------------------------------ | ----------------------------------------------------------------------------- | ------------------------- |
| Strict Mode                    | [`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo) | Shell Mode                |
| { "$numberLong": "\<number>" } |                                                                               | NumberLong( "\<number>" ) |

`NumberLong`is a 64 bit signed integer. You must include quotation marks or it will be interpreted as a floating point number, resulting in a loss of accuracy.

For example, the following commands insert`9223372036854775807`as a`NumberLong`with and without quotation marks around the integer value:

```javascript
db.json.insert( { longQuoted : NumberLong("9223372036854775807") } )
db.json.insert( { longUnQuoted : NumberLong(9223372036854775807) } )
```

When you retrieve the documents, the value of`longUnQuoted`has changed, while`longQuoted`retains its accuracy:

```javascript
db.json.find()
{ "_id" : ObjectId("54ee1f2d33335326d70987df"), "longQuoted" : NumberLong("9223372036854775807") }
{ "_id" : ObjectId("54ee1f7433335326d70987e0"), "longUnQuoted" : NumberLong("-9223372036854775808") }
```

### NumberDecimal

New in version 3.4.

`data_numberdecimal`

|                                   |                                                                               |                              |
| --------------------------------- | ----------------------------------------------------------------------------- | ---------------------------- |
| Strict Mode                       | [`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo) | Shell Mode                   |
| { "$numberDecimal": "\<number>" } |                                                                               | NumberDecimal( "\<number>" ) |

`NumberDecimal`is a[high-precision decimal](https://github.com/mongodb/specifications/blob/master/source/bson-decimal128/decimal128.rst). You must include quotation marks, or the input number will be treated as a double, resulting in data loss.

For example, the following commands insert`123.40`as a`NumberDecimal`with and without quotation marks around the value:

```javascript
db.json.insert( { decimalQuoted : NumberDecimal("123.40") } )
db.json.insert( { decimalUnQuoted : NumberDecimal(123.40) } )
```

When you retrieve the documents, the value of`decimalUnQuoted`has changed, while`decimalQuoted`retains its specified precision:

```javascript
db.json.find()
{ "_id" : ObjectId("596f88b7b613bb04f80a1ea9"), "decimalQuoted" : NumberDecimal("123.40") }
{ "_id" : ObjectId("596f88c9b613bb04f80a1eaa"), "decimalUnQuoted" : NumberDecimal("123.400000000000") }
```


# MongoDB Extended JSON (v1)

On this page

* [Parsers and Supported Format](https://docs.mongodb.com/manual/reference/mongodb-extended-json/#parsers-and-supported-format)
* [BSON Data Types and Associated Representations](https://docs.mongodb.com/manual/reference/mongodb-extended-json/#bson-data-types-and-associated-representations)

[JSON](https://docs.mongodb.com/manual/reference/glossary/#term-json)can only represent a subset of the types supported by[BSON](https://docs.mongodb.com/manual/reference/glossary/#term-bson). To preserve type information, MongoDB adds the following extensions to the JSON format:

* *Strict mode*

  . Strict mode representations of BSON types conform to the

  [JSON RFC](http://www.json.org/)

  . Any JSON parser can parse these strict mode representations as key/value pairs; however, only the MongoDB internal JSON parser recognizes the type information conveyed by the format.
* `mongo`

  *Shell mode*

  . The MongoDB internal JSON parser and the

  [`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo)

  shell can parse this mode.

The representation used for the various data types depends on the context in which the JSON is parsed.

## Parsers and Supported Format

### Input in Strict Mode

The following can parse representations in strict mode\_with\_recognition of the type information.

* [REST Interfaces](https://docs.mongodb.com/ecosystem/tools/http-interfaces)
* [`mongoimport`](https://docs.mongodb.com/manual/reference/program/mongoimport/#bin.mongoimport)
* `--query`

  option of various MongoDB tools
* [MongoDB Compass](https://www.mongodb.com/products/compass)

Other JSON parsers, including[`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo)shell and[`db.eval()`](https://docs.mongodb.com/manual/reference/method/db.eval/#db.eval), can parse strict mode representations as key/value pairs, but\_without\_recognition of the type information.

### Input in`mongo`Shell Mode

The following can parse representations in`mongo`shell mode\_with\_recognition of the type information.

* [REST Interfaces](https://docs.mongodb.com/ecosystem/tools/http-interfaces)
* [`mongoimport`](https://docs.mongodb.com/manual/reference/program/mongoimport/#bin.mongoimport)
* `--query`

  option of various MongoDB tools
* [`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo)

  shell

### Output in Strict mode

[`mongoexport`](https://docs.mongodb.com/manual/reference/program/mongoexport/#bin.mongoexport)and[REST and HTTP Interfaces](https://docs.mongodb.com/ecosystem/tools/http-interfaces)output data in\_Strict mode\_.

### Output in`mongo`Shell Mode

[`bsondump`](https://docs.mongodb.com/manual/reference/program/bsondump/#bin.bsondump)outputs in`mongo`*Shell mode*.

## BSON Data Types and Associated Representations

The following presents the BSON data types and the associated representations in\_Strict mode\_and`mongo`\_Shell mode\_.

### Binary

`data_binary`

|                                              |                                                                               |                              |
| -------------------------------------------- | ----------------------------------------------------------------------------- | ---------------------------- |
| Strict Mode                                  | [`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo) | Shell Mode                   |
| { "$binary": "\<bindata>", "$type": "\<t>" } |                                                                               | BinData ( \<t>, \<bindata> ) |

* `<bindata>`is the base64 representation of a binary string.
* `<t>`is a representation of a single byte indicating the data type. In

  *Strict mode*

  it is a hexadecimal string, and in

  *Shell mode*

  it is an integer. See the extended bson documentation.

  <http://bsonspec.org/spec.html>

### Date

`data_date`

|                        |                                                                               |                      |
| ---------------------- | ----------------------------------------------------------------------------- | -------------------- |
| Strict Mode            | [`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo) | Shell Mode           |
| { "$date": "\<date>" } |                                                                               | new Date ( \<date> ) |

In\_Strict mode\_,`<date>`is an ISO-8601 date format with a mandatory time zone field following the template`YYYY-MM-DDTHH:mm:ss.mmm<+/-Offset>`.

The MongoDB JSON parser currently does not support loading ISO-8601 strings representing dates prior to the[Unix epoch](https://docs.mongodb.com/manual/reference/glossary/#term-unix-epoch). When formatting pre-epoch dates and dates past what your system’s`time_t`type can hold, the following format is used:

```
{ "$date" : { "$numberLong" : "
<
dateAsMilliseconds
>
" } }
```

In\_Shell mode\_,`<date>`is the JSON representation of a 64-bit signed integer giving the number of milliseconds since epoch UTC.

### Timestamp

`data_timestamp`

|                                            |                                                                               |                         |
| ------------------------------------------ | ----------------------------------------------------------------------------- | ----------------------- |
| Strict Mode                                | [`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo) | Shell Mode              |
| { "$timestamp": { "t": \<t>, "i": \<i> } } |                                                                               | Timestamp( \<t>, \<i> ) |

* `<`

  `t`

  `>`

  is the JSON representation of a 32-bit unsigned integer for seconds since epoch.
* `<`

  `i`

  `>`

  is a 32-bit unsigned integer for the increment.

### Regular Expression

`data_regex`

|                                                      |                                                                               |                        |
| ---------------------------------------------------- | ----------------------------------------------------------------------------- | ---------------------- |
| Strict Mode                                          | [`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo) | Shell Mode             |
| { "$regex": "\<sRegex>", "$options": "\<sOptions>" } |                                                                               | /\<jRegex>/\<jOptions> |

* `<`

  `sRegex`

  `>`

  is a string of valid JSON characters.
* `<`

  `jRegex`

  `>`

  is a string that may contain valid JSON characters and unescaped double quote (

  `"`

  ) characters, but may not contain unescaped forward slash (

  `/`

  ) characters.
* `<`

  `sOptions`

  `>`

  is a string containing the regex options represented by the letters of the alphabet.
* `<`

  `jOptions`

  `>`

  is a string that may contain only the characters ‘g’, ‘i’, ‘m’ and ‘s’ (added in v1.9). Because the

  `JavaScript`

  and

  `mongo`

  `Shell`

  representations support a limited range of options, any nonconforming options will be dropped when converting to this representation.

### OID

`data_oid`

|                     |                                                                               |                     |
| ------------------- | ----------------------------------------------------------------------------- | ------------------- |
| Strict Mode         | [`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo) | Shell Mode          |
| { "$oid": "\<id>" } |                                                                               | ObjectId( "\<id>" ) |

`<id>`is a 24-character hexadecimal string.

### DB Reference

`data_ref`

|                                       |                                                                               |                           |
| ------------------------------------- | ----------------------------------------------------------------------------- | ------------------------- |
| Strict Mode                           | [`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo) | Shell Mode                |
| { "$ref": "\<name>", "$id": "\<id>" } |                                                                               | DBRef("\<name>", "\<id>") |

* `<`

  `name`

  `>`

  is a string of valid JSON characters.
* `<`

  `id`

  `>`

  is any valid extended JSON type.

### Undefined Type

`data_undefined`

|                        |                                                                               |            |
| ---------------------- | ----------------------------------------------------------------------------- | ---------- |
| Strict Mode            | [`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo) | Shell Mode |
| { "$undefined": true } |                                                                               | undefined  |

The representation for the JavaScript/BSON undefined type.

You\_cannot\_use`undefined`in query documents. Consider the following document inserted into the`people`collection:

```javascript
db.people.insert( { name : "Sally", age : undefined } )
```

The following queries return an error:

```javascript
db.people.find( { age : undefined } )
db.people.find( { age : { $gte : undefined } } )
```

However, you can query for undefined values using[`$type`](https://docs.mongodb.com/manual/reference/operator/query/type/#op._S_type), as in:

```javascript
db.people.find( { age : { $type : 6 } } )
```

This query returns all documents for which the`age`field has value`undefined`.

### MinKey

`data_minkey`

|                  |                                                                               |            |
| ---------------- | ----------------------------------------------------------------------------- | ---------- |
| Strict Mode      | [`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo) | Shell Mode |
| { "$minKey": 1 } |                                                                               | MinKey     |

The representation of the MinKey BSON data type that compares lower than all other types. See[Comparison/Sort Order](https://docs.mongodb.com/manual/reference/bson-type-comparison-order/#faq-dev-compare-order-for-bson-types)for more information on comparison order for BSON types.

### MaxKey

`data_maxkey`

|                  |                                                                               |            |
| ---------------- | ----------------------------------------------------------------------------- | ---------- |
| Strict Mode      | [`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo) | Shell Mode |
| { "$maxKey": 1 } |                                                                               | MaxKey     |

The representation of the MaxKey BSON data type that compares higher than all other types. See[Comparison/Sort Order](https://docs.mongodb.com/manual/reference/bson-type-comparison-order/#faq-dev-compare-order-for-bson-types)for more information on comparison order for BSON types.

### NumberLong

New in version 2.6.

`data_numberlong`

|                                |                                                                               |                           |
| ------------------------------ | ----------------------------------------------------------------------------- | ------------------------- |
| Strict Mode                    | [`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo) | Shell Mode                |
| { "$numberLong": "\<number>" } |                                                                               | NumberLong( "\<number>" ) |

`NumberLong`is a 64 bit signed integer. You must include quotation marks or it will be interpreted as a floating point number, resulting in a loss of accuracy.

For example, the following commands insert`9223372036854775807`as a`NumberLong`with and without quotation marks around the integer value:

```javascript
db.json.insert( { longQuoted : NumberLong("9223372036854775807") } )
db.json.insert( { longUnQuoted : NumberLong(9223372036854775807) } )
```

When you retrieve the documents, the value of`longUnQuoted`has changed, while`longQuoted`retains its accuracy:

```javascript
db.json.find()
{ "_id" : ObjectId("54ee1f2d33335326d70987df"), "longQuoted" : NumberLong("9223372036854775807") }
{ "_id" : ObjectId("54ee1f7433335326d70987e0"), "longUnQuoted" : NumberLong("-9223372036854775808") }
```

### NumberDecimal

New in version 3.4.

`data_numberdecimal`

|                                   |                                                                               |                              |
| --------------------------------- | ----------------------------------------------------------------------------- | ---------------------------- |
| Strict Mode                       | [`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo) | Shell Mode                   |
| { "$numberDecimal": "\<number>" } |                                                                               | NumberDecimal( "\<number>" ) |

`NumberDecimal`is a[high-precision decimal](https://github.com/mongodb/specifications/blob/master/source/bson-decimal128/decimal128.rst). You must include quotation marks, or the input number will be treated as a double, resulting in data loss.

For example, the following commands insert`123.40`as a`NumberDecimal`with and without quotation marks around the value:

```javascript
db.json.insert( { decimalQuoted : NumberDecimal("123.40") } )
db.json.insert( { decimalUnQuoted : NumberDecimal(123.40) } )
```

When you retrieve the documents, the value of`decimalUnQuoted`has changed, while`decimalQuoted`retains its specified precision:

```javascript
db.json.find()
{ "_id" : ObjectId("596f88b7b613bb04f80a1ea9"), "decimalQuoted" : NumberDecimal("123.40") }
{ "_id" : ObjectId("596f88c9b613bb04f80a1eaa"), "decimalUnQuoted" : NumberDecimal("123.400000000000") }
```


# 安装 MongoDB

在本页面

* [MongoDB社区版安装教程](https://docs.mongodb.com/v4.2/installation/#mongodb-community-edition-installation-tutorials)
* [MongoDB企业版安装教程](https://docs.mongodb.com/v4.2/installation/#mongodb-enterprise-edition-installation-tutorials)
* [将社区版升级到企业版教程](https://docs.mongodb.com/v4.2/installation/#upgrade-community-edition-to-enterprise-edition-tutorials)
* [支持平台](https://docs.mongodb.com/v4.2/installation/#supported-platforms)

MongoDB有两个服务器版本：\_社区版\_和 *企业版*。

MONGODB ATLAS

[MongoDB Atlas](https://www.mongodb.com/cloud/atlas?tck=docs_server) 是MongoDB公司提供的MongoDB云服务，无需安装开销，并提供免费的入门套餐。

手册的这部分包含有关安装MongoDB的信息。

* 有关将当前部署升级到MongoDB 4.2的说明，请参阅[升级过程](https://docs.mongodb.com/v4.2/release-notes/4.2/#upgrade)。
* 有关升级到当前版本的最新修补程序版本的说明，请参阅[升级到MongoDB的最新版本](https://docs.mongodb.com/v4.2/tutorial/upgrade-revision/)。

## MongoDB社区版安装教程

MongoDB社区版安装教程包括：

| 平台      | 对应教程                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Linux   | [在Red Hat或CentOS上安装MongoDB社区版](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-red-hat/) [在Ubuntu上安装MongoDB Community Edition](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-ubuntu/) [在Debian上安装MongoDB社区版](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-debian/) [在SUSE上安装MongoDB社区版](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-suse/) [在Amazon Linux上安装MongoDB社区版](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-amazon/) |
| macOS   | [在macOS上安装MongoDB社区版](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-os-x/)                                                                                                                                                                                                                                                                                                                                                                                                      |
| Windows | [在Windows上安装MongoDB社区版](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-windows/)                                                                                                                                                                                                                                                                                                                                                                                                 |

## MongoDB企业版安装教程

MongoDB企业版安装教程包括：

| 平台      | 对应教程                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Linux   | [在Red Hat或CentOS上安装MongoDB企业版](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-red-hat/) [在Ubuntu上安装MongoDB企业版](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-ubuntu/) [在Debian上安装MongoDB企业版](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-debian/) [在SUSE上安装MongoDB企业版](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-suse/) [在Amazon Linux上安装MongoDB企业版](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-amazon/) |
| macOS   | [在macOS上安装MongoDB企业版](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-os-x/)                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| Windows | [在Windows上安装MongoDB企业版](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-windows/)                                                                                                                                                                                                                                                                                                                                                                                                                              |
| Docker  | [使用Docker安装MongoDB企业版](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-with-docker/)                                                                                                                                                                                                                                                                                                                                                                                                                              |

## 将社区版升级到企业版教程

重要

不要使用这些说明升级到另一个发行版本。要升级发行版本，请参阅相应的发行升级说明，例如[Upgrade to MongoDB 4.2](https://docs.mongodb.com/v4.2/release-notes/4.2/#upgrade)。

* [升级到MongoDB企业版（单节点）](https://docs.mongodb.com/v4.2/tutorial/upgrade-to-enterprise-standalone/)
* [升级到MongoDB企业版（副本集）](https://docs.mongodb.com/v4.2/tutorial/upgrade-to-enterprise-replica-set/)
* [升级到MongoDB企业版（分片集群）](https://docs.mongodb.com/v4.2/tutorial/upgrade-to-enterprise-sharded-cluster/)

## 支持的平台

*在版本3.4中进行了更改：* MongoDB不再支持32位x86平台。

### x86\_64

平台支持停产通知

| Ubuntu 14.04 | 支持已在MongoDB 4.2+中删除。 |
| ------------ | -------------------- |
| Debian 8     | 支持已在MongoDB 4.2+中删除。 |
| macOS 10.11  | 支持已在MongoDB 4.2+中删除。 |

*即将停产的通知*：

| Windows 8.1 / 2012R2 | MongoDB将在将来的版本中终止支持。 |
| -------------------- | -------------------- |
| Windows 8/2012       | MongoDB将在后续版本中终止支持。  |
| Windows 7 / 2008R2   | MongoDB将在后续版本中终止支持。  |

| 平台                                                                                                      | 4.2社区版与企业版 | 4.0社区版与企业版 | 3.6社区版与企业版 | 3.4社区版与企业版 |
| ------------------------------------------------------------------------------------------------------- | :--------: | :--------: | :--------: | :--------: |
| Amazon Linux 2                                                                                          |      ✓     |      ✓     |            |            |
| Amazon Linux 2013.03及更高版本                                                                               |      ✓     |      ✓     |      ✓     |      ✓     |
| Debian 10                                                                                               |   4.2.1+   |            |            |            |
| Debian 9                                                                                                |      ✓     |      ✓     |   3.6.5+   |            |
| Debian 8                                                                                                |            |      ✓     |      ✓     |      ✓     |
| RHEL / CentOS / Oracle Linux [\[1\]](https://docs.mongodb.com/v4.2/installation/#oracle-linux) 8.0及更高版本 |   4.2.1+   |   4.0.14+  |   3.6.17+  |            |
| RHEL / CentOS / Oracle Linux [\[1\]](https://docs.mongodb.com/v4.2/installation/#oracle-linux) 7.0及更高版本 |      ✓     |      ✓     |      ✓     |      ✓     |
| RHEL / CentOS / Oracle Linux [\[1\]](https://docs.mongodb.com/v4.2/installation/#oracle-linux) 6.2及更高版本 |      ✓     |      ✓     |      ✓     |      ✓     |
| SLES 15                                                                                                 |   4.2.1+   |            |            |            |
| SLES 12                                                                                                 |      ✓     |      ✓     |      ✓     |      ✓     |
| Solaris 11 64位                                                                                          |            |            |            |    仅社区版    |
| Ubuntu 18.04                                                                                            |      ✓     |   4.0.1+   |            |            |
| Ubuntu 16.04                                                                                            |      ✓     |      ✓     |      ✓     |      ✓     |
| Ubuntu 14.04                                                                                            |            |      ✓     |      ✓     |      ✓     |
| Windows Server 2019                                                                                     |      ✓     |            |            |            |
| Windows 10 /Server 2016                                                                                 |      ✓     |      ✓     |      ✓     |      ✓     |
| Windows 8.1 / Server 2012 R2                                                                            |      ✓     |      ✓     |      ✓     |      ✓     |
| Windows 8 /Server 012                                                                                   |      ✓     |      ✓     |      ✓     |      ✓     |
| Windows 7 / Server 2008 R2                                                                              |      ✓     |      ✓     |      ✓     |      ✓     |
| Windows Vista                                                                                           |            |            |            |      ✓     |
| macOS 10.13及更高版本                                                                                        |      ✓     |      ✓     |            |            |
| macOS 10.12                                                                                             |      ✓     |      ✓     |      ✓     |      ✓     |
| macOS 10.11                                                                                             |            |      ✓     |      ✓     |      ✓     |
| macOS 10.10                                                                                             |            |            |      ✓     |      ✓     |

|      |                                                                                                                                                                                                                                                                                           |
| ---- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| \[1] | *（*[*1*](https://docs.mongodb.com/v4.2/installation/#id1)*，*[*2*](https://docs.mongodb.com/v4.2/installation/#id2)*，*[*3*](https://docs.mongodb.com/v4.2/installation/#id3)\_）\_的MongoDB仅支持运行Red Hat Compatible Kernel (RHCK)的Oracle的Linux。MongoDB不支持Unbreakable Enterprise Kernel (UEK)。 |
|      |                                                                                                                                                                                                                                                                                           |

### ARM64

平台支持停产通知

| Ubuntu 16.04 ARM64 | 支持已在MongoDB Community 4.2+中删除。 |
| ------------------ | ------------------------------ |
|                    |                                |

| 平台           | 4.2社区版与企业版 | 4.0社区版与企业版 | 3.6社区版与企业版 | 3.4社区版与企业版 |
| ------------ | :--------: | :--------: | :--------: | :--------: |
| Ubuntu 18.04 |    仅社区版    |            |            |            |
| Ubuntu 16.04 |    仅企业版    |      ✓     |      ✓     |      ✓     |

### PPC64LE（MongoDB企业版）

平台支持停产通知

| Ubuntu 16.04 PPC64LE | 支持已在MongoDB 4.2+中删除。 |
| -------------------- | -------------------- |
|                      |                      |

| 平台              | 4.2企业 | 4.0企业 |    3.6企业    |    3.4企业    |
| --------------- | :---: | :---: | :---------: | :---------: |
| RHEL / CentOS 7 |   ✓   |   ✓   |      ✓      |      ✓      |
| Ubuntu 18.04    |   ✓   |       |             |             |
| Ubuntu 16.04    |       |   ✓   | 从3.6.13开始删除 | 从3.4.21开始删除 |

### s390x

| 平台              | 4.2社区版与企业版 | 4.0企业版 |    3.6企业版   |    3.4企业版   |
| --------------- | :--------: | :----: | :---------: | :---------: |
| RHEL / CentOS 7 |      ✓     | 4.0.6+ | 从3.6.17开始删除 | 从3.4.14开始删除 |
| RHEL / CentOS 6 |      ✓     |    ✓   | 从3.6.14开始删除 | 从3.4.22开始删除 |
| SLES12          |      ✓     | 4.0.6+ | 从3.6.17开始删除 | 从3.4.15开始删除 |
| Ubuntu 18.04    |   4.2.1+   | 4.0.6+ |             |             |

← [MongoDB扩展JSON（v1）](https://docs.mongodb.com/v4.2/reference/mongodb-extended-json-v1/)\
[安装MongoDB社区版](https://docs.mongodb.com/v4.2/administration/install-community/) →

原文链接：<https://docs.mongodb.com/v4.2/installation/>

译者：桂陈

### MongoDB中文社区

![MongoDB中文社区—MongoDB爱好者技术交流平台](https://mongoing.com/wp-content/uploads/2020/09/6de8a4680ef684d-2.png)

| 资源列表推荐             | 资源入口                                                                                                                                                                                                                                                                       |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| MongoDB中文社区官网      | <https://mongoing.com/>                                                                                                                                                                                                                                                    |
| 微信服务号 ——最新资讯和优质文章  | Mongoing中文社区（mongoing-mongoing）                                                                                                                                                                                                                                            |
| 微信订阅号 ——发布文档翻译内容   | MongoDB中文用户组（mongoing123）                                                                                                                                                                                                                                                  |
| 官方微信号 —— 官方最新资讯    | MongoDB数据库（MongoDB-China）                                                                                                                                                                                                                                                  |
| MongoDB中文社区组委会成员介绍 | <https://mongoing.com/core-team-members>                                                                                                                                                                                                                                   |
| MongoDB中文社区翻译小组介绍  | <https://mongoing.com/translators>                                                                                                                                                                                                                                         |
| MongoDB中文社区微信技术交流群 | 添加社区助理小芒果微信（ID:mongoingcom），并备注 mongo                                                                                                                                                                                                                                      |
| MongoDB中文社区会议及文档资源 | <https://mongoing.com/resources>                                                                                                                                                                                                                                           |
| MongoDB中文社区大咖博客    | [基础知识](https://mongoing.com/basic-knowledge) [性能优化](https://mongoing.com/performance-optimization) [原理解读](https://mongoing.com/interpretation-of-principles) [运维监控](https://mongoing.com/operation-and-maintenance-monitoring) [最佳实践](https://mongoing.com/best-practices) |
| MongoDB白皮书         | <https://mongoing.com/mongodb-download-white-paper>                                                                                                                                                                                                                        |
| MongoDB初学者教程-7天入门  | <https://mongoing.com/mongodb-beginner-tutorial>                                                                                                                                                                                                                           |
| 社区活动邮件订阅           | <https://sourl.cn/spszjN>                                                                                                                                                                                                                                                  |


# 安装MongoDB社区版

下方文档提供了安装MongoDB社区版的说明。

* [在Linux上安装](https://docs.mongodb.com/v4.2/administration/install-on-linux/)

  在Linux上安装MongoDB Community Edition和必需的依赖项。
* [在macOS上安装](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-os-x/)

  从MongoDB归档文件在macOS系统上安装MongoDB Community Edition。
* [在Windows上安装](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-windows/)

  在Windows系统上安装MongoDB Community Edition，并可以选择将MongoDB作为Windows服务启动。

← [安装MongoDB](https://docs.mongodb.com/v4.2/installation/)[在Linux上安装MongoDB社区版](https://docs.mongodb.com/v4.2/administration/install-on-linux/) →

原文链接：<https://docs.mongodb.com/v4.2/administration/install-community/>

译者：小芒果


# 在Linux上安装MongoDB社区版

这些文档提供了为受支持的Linux系统安装MongoDB社区版的说明。

## 推荐

为了获得最佳的安装体验，MongoDB提供了适用于流行Linux发行版的软件包。这些软件包是运行MongoDB的首选方式。以下指南详细介绍了这些系统的安装过程：

* [在Red Hat上安装](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-red-hat/)

  使用`.rpm`软件包在Red Hat企业版和相关Linux系统上安装MongoDB社区版。
* [在Ubuntu上安装](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-ubuntu/)

  使用`.deb`软件包在Ubuntu Linux系统上安装MongoDB社区版。
* [在Debian上安装](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-debian/)

  使用`.deb` 软件包在Debian系统上安装MongoDB社区版。
* [在SUSE上安装](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-suse/)

  使用`.rpm`软件包在SUSE Linux系统上安装MongoDB Community Edition 。
* [在亚马逊上安装](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-amazon/)

  使用`.rpm`软件包在Amazon Linux AMI系统上安装MongoDB社区版。

WINDOWS LINUX子系统（WSL）-不支持

MongoDB不支持Linux的Windows子系统（WSL）。

原文链接：<https://docs.mongodb.com/v4.2/administration/install-on-linux/>

译者：小芒果


# 在macOS上安装MongoDB社区版

在本页面

* [概述](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-os-x/#overview)
* [注意事项](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-os-x/#considerations)
* [安装MongoDB社区版](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-os-x/#install-mongodb-community-edition)
* [附加信息](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-os-x/#additional-information)

MONGODB ATLAS

[MongoDB Atlas](https://www.mongodb.com/cloud/atlas?tck=docs_server) 是MongoDB公司提供的MongoDB云服务，无需安装开销，并提供免费的入门套餐。

## 概述

使用本教程可使用第三方`brew`包管理器在macOS上安装MongoDB 4.2社区版。

### MongoDB版本

本教程将安装MongoDB 4.2社区版。要安装其他版本的MongoDB，请使用此页面左上角的版本下拉菜单选择该版本的文档。

## 注意事项

### 平台支持

MongoDB 4.2 社区版支持macOS 10.12或更高版本。

有关更多信息，请参见[支持的平台](https://docs.mongodb.com/v4.2/administration/production-notes/#prod-notes-supported-platforms)。

### 生产注意事项

在生产环境中部署MongoDB之前，请考虑 [生产说明](https://docs.mongodb.com/v4.2/administration/production-notes/)文档，该文档提供了生产MongoDB部署的性能注意事项和配置建议。

## 安装MongoDB社区版[¶](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-os-x/#install-mongodb-community-edition)

### 前提条件

如果您在OSX主机上安装了Homebrew `brew`软件包， \_并且\_以前已经使用了官方的 [MongoDB Homebrew Tap](https://github.com/mongodb/homebrew-brew)，请跳过前提条件并转到“ [过程”](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-os-x/#install)步骤。

#### 安装XCode

Apple的XCode包含所需的`brew`命令行工具，可在App Store上免费获得。确保您正在运行最新版本。

#### 安装Homebrew

OSX 默认不包括Homebrew`brew`软件包。按照 [官方说明进行](https://brew.sh/#install)安装`brew`。

#### 点击MongoDB Homebrew

在终端上发出以下命令，以点击官方的 [MongoDB Homebrew Tap](https://github.com/mongodb/homebrew-brew)：

复制

```
brew tap mongodb/brew
```

### 过程

请按照以下步骤使用第三方`brew`程序包管理器安装MongoDB社区版。

在终端上，发出以下命令：

复制

```
brew install mongodb-community@4.2
```

提示

如果您以前安装了该公式的较旧版本，则可能会遇到ChecksumMismatchError。若要解决，请参阅 [ChecksumMismatchError故障排除](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-os-x/#troubleshooting-checksumerror)。

除[二进制文件外](https://docs.mongodb.com/v4.2/reference/program/)，安装还会创建：

* [配置文件](https://docs.mongodb.com/v4.2/reference/configuration-options/) （`/usr/local/etc/mongod.conf`）
* （）[`log directory path`](https://docs.mongodb.com/v4.2/reference/configuration-options/#systemLog.path)`/usr/local/var/log/mongodb`
* （）[`data directory path`](https://docs.mongodb.com/v4.2/reference/configuration-options/#storage.dbPath)`/usr/local/var/mongodb`

### 运行MongoDB社区版

请按照以下步骤运行MongoDB社区版。这些说明假定您使用的是默认设置。

您可以使用`brew`来将MongoDB作为macOS服务运行，也可以作为后台进程手动运行MongoDB。建议将MongoDB作为macOS服务运行，因为这样做会自动设置正确的系统`ulimit`值（有关更多信息，请参阅 [ulimit设置](https://docs.mongodb.com/v4.2/reference/ulimit/#ulimit-settings)）。

* 要将MongoDB（即[`mongod`](https://docs.mongodb.com/v4.2/reference/program/mongod/#bin.mongod)进程）**作为macOS服务运行**，请发出以下命令：

  复制

  ```
  brew services start mongodb-community@4.2
  ```

  要停止[`mongod`](https://docs.mongodb.com/v4.2/reference/program/mongod/#bin.mongod)作为macOS服务运行，请根据需要使用以下命令：

  复制

  ```
  brew services stop mongodb-community@4.2
  ```
* 要将MongoDB（即[`mongod`](https://docs.mongodb.com/v4.2/reference/program/mongod/#bin.mongod)进程）**作为后台进程手动**运行，请发出以下命令：

  复制

  ```
  mongod --config /usr/local/etc/mongod.conf --fork
  ```

  要停止[`mongod`](https://docs.mongodb.com/v4.2/reference/program/mongod/#bin.mongod)作为后台进程运行，请从**mongo** shell 连接到[`mongod`](https://docs.mongodb.com/v4.2/reference/program/mongod/#bin.mongod)，然后根据需要发出[`shutdown`](https://docs.mongodb.com/v4.2/reference/command/shutdown/#dbcmd.shutdown)命令。

两种方法都使用在安装过程中创建的`/usr/local/etc/mongod.conf`文件。您也可以将自己的MongoDB [配置选项](https://docs.mongodb.com/v4.2/reference/configuration-options/)添加到此文件。

MACOS阻止`MONGOD`打开

`mongod`安装后，macOS可能无法运行。如果在启动时收到安全错误，`mongod` 显示无法识别或验证开发人员，请执行以下操作以授予`mongod`运行权限：

* 打开\_系统偏好设置\_
* 选择“ \_安全性和隐私”\_窗格。
* 在\_常规\_选项卡下，单击关于`mongod`消息右侧的按钮，根据您的macOS版本标记为“始终**打开”** 或“ **始终允许”**。

要验证MongoDB是否正在运行，请在正在运行的进程中搜索`mongod`：

复制

```
ps aux | grep -v grep | grep mongod
```

您还可以查看日志文件以查看`mongod`进程的当前状态 ：`/usr/local/var/log/mongodb/mongo.log`。

### 连接和使用MongoDB

要开始使用MongoDB，请将[`mongo`](https://docs.mongodb.com/v4.2/reference/program/mongo/#bin.mongo)shell 连接到正在运行的实例。在新终端上，发出以下命令：

复制

```
mongo
```

* MACOS阻止`MONGOD`打开

  `mongod`安装后，macOS可能无法运行。如果在启动时收到安全错误，`mongod` 显示无法识别或验证开发人员，请执行以下操作以授予`mongod`运行权限：

  * 打开\_系统偏好设置\_
  * 选择“ \_安全性和隐私”\_窗格。
  * 在\_常规\_选项卡下，单击关于`mongod`消息右侧的按钮，根据您的macOS版本标记为“始终**打开”** 或“ **始终允许”**。

有关CRUD（创建，读取，更新，删除）操作的信息，请参阅：

* [插入文档](https://docs.mongodb.com/v4.2/tutorial/insert-documents/)
* [查询文档](https://docs.mongodb.com/v4.2/tutorial/query-documents/)
* [更新文档](https://docs.mongodb.com/v4.2/tutorial/update-documents/)
* [删除文档](https://docs.mongodb.com/v4.2/tutorial/remove-documents/)

## 其他信息

### 默认为localhost绑定

默认情况下，MongoDB在启动时将[`bindIp`](https://docs.mongodb.com/v4.2/reference/configuration-options/#net.bindIp)设置为 `127.0.0.1`，绑定到localhost网络接口。这意味着`mongod`只能接受来自同一计算机上运行的客户端的连接。除非将此值设置为有效的网络接口，否则远程客户端将无法连接到`mongod`，并且`mongod`不能初始化[副本集](https://docs.mongodb.com/v4.2/reference/glossary/#term-replica-set)。

可以配置以下值：

* 在MongoDB配置文件中使用[`bindIp`](https://docs.mongodb.com/v4.2/reference/configuration-options/#net.bindIp)，或
* 通过命令行参数 [`--bind_ip`](https://docs.mongodb.com/v4.2/reference/program/mongod/#cmdoption-mongod-bind-ip)

警告

绑定到非本地主机（例如，可公共访问）的IP地址之前，请确保已保护群集免受未经授权的访问。有关安全建议的完整列表，请参阅“ [安全清单”](https://docs.mongodb.com/v4.2/administration/security-checklist/)。至少应考虑 [启用身份验证](https://docs.mongodb.com/v4.2/administration/security-checklist/#checklist-auth)并 [强化网络基础架构](https://docs.mongodb.com/v4.2/core/security-hardening/)。

有关配置的更多信息[`bindIp`](https://docs.mongodb.com/v4.2/reference/configuration-options/#net.bindIp)，请参见 [IP绑定](https://docs.mongodb.com/v4.2/core/security-mongodb-configuration/)。

### 对ChecksumMismatchError进行故障排除[¶](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-os-x/#troubleshooting-checksummismatcherror)

如果您以前安装了该公式的较旧版本，则可能会遇到类似于以下内容的ChecksumMismatchError：

复制

```
Error: An exception occurred within a child process:

  ChecksumMismatchError: SHA256 mismatch

Expected: c7214ee7bda3cf9566e8776a8978706d9827c1b09017e17b66a5a4e0c0731e1f

  Actual: 6aa2e0c348e8abeec7931dced1f85d4bb161ef209c6af317fe530ea11bbac8f0

 Archive: /Users/kay/Library/Caches/Homebrew/downloads/a6696157a9852f392ec6323b4bb697b86312f0c345d390111bd51bb1cbd7e219--mongodb-macos-x86_64-4.2.0.tgz

To retry an incomplete download, remove the file above.
```

修复：

1. 删除下载的`.tgz`档案。
2. 点击公式。

复制

```
brew untap mongodb/brew && brew tap mongodb/brew
```

1. 重试安装。

   复制

   ```
   brew install mongodb-community@4.2
   ```

← [Install MongoDB Community on Amazon Linux using .tgz Tarball](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-amazon-tarball/)\
[Install MongoDB Community on macOS using .tgz Tarball](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-os-x-tarball/) →

原文链接：<https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-os-x/>

译者：小芒果


# 在Windows上安装MongoDB社区版

在本页面

* [概述](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-windows/#overview)
* [注意事项](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-windows/#considerations)
* [安装MongoDB社区版](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-windows/#install-mongodb-community-edition)
* [将MongoDB社区版作为Windows服务运行](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-windows/#run-mongodb-community-edition-as-a-windows-service)
* [从命令解释器运行MongoDB社区版](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-windows/#run-mongodb-community-edition-from-the-command-interpreter)
* [其他注意事项](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-windows/#additional-considerations)

MONGODB ATLAS

[MongoDB Atlas](https://www.mongodb.com/cloud/atlas?tck=docs_server) 是MongoDB公司提供的MongoDB云服务，无需安装开销，并提供免费的入门套餐。

## 概述

使用本教程可以使用默认安装向导在Windows上安装MongoDB 4.2社区版。

### MongoDB版本

本教程将安装MongoDB 4.2社区版。要安装其他版本的MongoDB社区，请使用此页面左上角的版本下拉菜单选择该版本的文档。

### 安装方法

本教程使用默认安装向导在Windows上安装MongoDB。或者，您可以选择使用`msiexec.exe`命令行（`cmd.exe`）以无人参与的方式在Windows上安装MongoDB 。这对于希望使用自动化部署MongoDB的系统管理员很有用。

➤有关说明，请参阅[使用msiexec.exe在Windows上安装MongoDB社区版](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-windows-unattended/)。

## 注意事项

### 平台支持

MongoDB 4.2 社区版在[x86\_64](https://docs.mongodb.com/v4.2/administration/production-notes/#prod-notes-supported-platforms-x86-64)架构上支持Windows 的以下 **64位**版本 ：

* Windows Server 2019
* Windows 10 / Windows Server 2016
* Windows 8.1 / Windows Server 2012 R2
* Windows 8 / Windows Server 2012
* Windows 7 / Windows Server 2008 R2

MongoDB仅支持这些平台的64位版本。

有关更多信息，请参见[支持的平台](https://docs.mongodb.com/v4.2/administration/production-notes/#prod-notes-supported-platforms)。

### 生产注意事项

在生产环境中部署MongoDB之前，请考虑 [生产说明](https://docs.mongodb.com/v4.2/administration/production-notes/)文档，该文档提供了生产MongoDB部署的性能注意事项和配置建议。

## 安装MongoDB社区版

### 前提条件

Windows 10之前的Windows版本上的用户必须在安装MongoDB之前安装以下更新：

➤ [Windows系统Universal C运行时更新](https://support.microsoft.com/en-us/help/2999226/update-for-universal-c-runtime-in-windows)

Windows 10，Server 2016和Server 2019上的用户不需要此更新。

### 程序

请按照以下步骤使用MongoDB安装程序向导安装MongoDB社区版。安装过程将同时安装MongoDB二进制文件和默认[配置文件](https://docs.mongodb.com/v4.2/reference/configuration-options/) `<install directory>\bin\mongod.cfg`。

#### 1. 下载安装程序。

从以下链接下载MongoDB社区安装程序`.msi`：

➤ [MongoDB的下载中心](https://www.mongodb.com/try/download/community?tck=docs_server)

1. 在“ \*\*版本”\*\*下拉列表中，选择要下载的MongoDB版本。
2. 在**平台**下拉菜单中，选择**Windows**。
3. 在**Package**下拉列表中，选择**msi**。
4. 点击**下载**。

#### 2. 运行MongoDB安装程序。

例如，从Windows资源管理器/文件资源管理器中：

1. 转到下载MongoDB安装程序的目录（`.msi`文件）。默认情况下，这是您的`Downloads`目录。
2. 双击`.msi`文件。

#### 3. 遵循MongoDB社区版安装向导。

该向导将引导您完成MongoDB和MongoDB Compass的安装。

1. * **选择安装类型**

     您可以选择“ **完整”**（建议大多数用户使用）或“ \*\*自定义”\*\*安装类型。“ **完整**设置”选项会将MongoDB和MongoDB工具安装到默认位置。使用“ **自定义** 安装”选项可以指定要安装的可执行文件以及安装位置。
2. * **服务配置**

     从MongoDB 4.0开始，您可以在安装过程中将MongoDB设置为Windows服务，也可以仅安装二进制文件。

     * MongoDB服务
     * MongoDB

     以下内容将MongoDB安装并配置为Windows服务。 从MongoDB 4.0开始，您可以在安装过程中将MongoDB配置和启动为Windows服务，并在成功安装后启动MongoDB服务。\
     ![Image of the MongoDB Installer wizard - Service Configuration.](https://docs.mongodb.com/v4.2/_images/windows-installer.png)

     * 选择“ **将MongoDB作为服务安装”**。
     * 选择以下任一项：
       * **以网络服务用户身份运行服务**（默认）

         这是Windows内置的Windows用户帐户

         **或者**
       * **以本地或域用户身份运行服务**
         * 对于现有的本地用户帐户，请为“ \*\*帐户域”\*\*指定一个句点（即`.`），并为该用户指定“ \*\*帐户名”\*\*和“ **帐户密码** ”。
         * 对于现有的域用户，请为该用户指定“ **帐户域”**，“ \*\*帐户名称”\*\*和“ **帐户密码** ”。
         * **服务名称**。指定服务名称。默认名称为`MongoDB`。如果您已经拥有使用指定名称的服务，则必须选择另一个名称。
         * **数据目录**。指定数据目录，它对应于 [`--dbpath`](https://docs.mongodb.com/v4.2/reference/program/mongod/#cmdoption-mongod-dbpath)。如果目录不存在，安装程序将创建该目录并设置对服务用户的目录访问权限。
         * **日志目录**。指定日志目录，它对应于 [`--logpath`](https://docs.mongodb.com/v4.2/reference/program/mongod/#cmdoption-mongod-logpath)。如果目录不存在，安装程序将创建该目录并设置对服务用户的目录访问权限。
3. * 对于Windows 8或更高版本，您可以让向导安装 [MongoDB Compass](https://www.mongodb.com/products/compass)。要安装Compass，请选择**Install MongoDB Compass**（默认）。

     注意

     安装脚本需要PowerShell 3.0或更高版本。如果您使用Windows 7，请取消单击 **Install MongoDB Compass**。您可以[从下载中心](https://www.mongodb.com/download-center/compass?tck=docs_server)手动[下载Compass](https://www.mongodb.com/download-center/compass?tck=docs_server)。
4. 准备就绪后，点击**安装**。

### 如果您将MongoDB安装为Windows服务

成功安装后将启动MongoDB服务[\[1\]](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-windows/#cfg)。

要开始使用MongoDB，请将[`mongo.exe`](https://docs.mongodb.com/v4.2/reference/program/mongo/#bin.mongo) shell 连接到正在运行的MongoDB实例。要么：

* 在Windows资源管理器/文件资源管理器中，转到目录`C:\Program Files\MongoDB\Server\4.2\bin\`，然后双击 [mongo.exe\`](https://docs.mongodb.com/v4.2/reference/program/mongo/#bin.mongo)
* 或者，使用管理特权打开**命令解释器**并运行：

  复制

  ```
  “ C：\ Program Files \ MongoDB \ Server \ 4.2 \ bin \ mongo.exe”
  ```

有关CRUD（创建，读取，更新，删除）操作的信息，请参阅：

* [插入文档](https://docs.mongodb.com/v4.2/tutorial/insert-documents/)
* [查询文档](https://docs.mongodb.com/v4.2/tutorial/query-documents/)
* [更新文档](https://docs.mongodb.com/v4.2/tutorial/update-documents/)
* [删除文档](https://docs.mongodb.com/v4.2/tutorial/remove-documents/)

|                                                                                 |                                                         |
| ------------------------------------------------------------------------------- | ------------------------------------------------------- |
| [\[1\]](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-windows/#id1) | 使用配置文件`<install directory>\bin\mongod.cfg`配置MongoDB实例 。 |
|                                                                                 |                                                         |

### 如果您没有将MongoDB安装为Windows服务[¶](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-windows/#if-you-did-not-install-mongodb-as-a-windows-service)

如果您仅安装了可执行文件而没有将MongoDB作为Windows服务安装，则必须手动启动MongoDB实例。

有关启动MongoDB实例的说明，请参阅[从命令解释器运行MongoDB社区版](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-windows/#run-mongodb-from-cmd)。

## 将社区版MongoDB作为Windows服务运行

从版本4.0开始，您可以在安装过程中将MongoDB安装和配置为 **Windows服务**，并在成功安装后启动MongoDB服务。使用配置文件 `<install directory>\bin\mongod.cfg`配置MongoDB 。

### 将社区版MongoDB作为Windows服务启动

要启动/重新启动MongoDB服务，请使用服务控制台：

1. 在服务控制台中，找到MongoDB服务。
2. 右键单击MongoDB服务，然后单击**启动**。

要开始使用MongoDB，请将[`mongo.exe`](https://docs.mongodb.com/v4.2/reference/program/mongo/#bin.mongo) shell 连接到正在运行的MongoDB实例。要进行连接，请打开具有管理权限的**命令解释器**并运行：

复制

```
“ C：\ Program Files \ MongoDB \ Server \ 4.2 \ bin \ mongo.exe”
```

有关[`mongo.exe`](https://docs.mongodb.com/v4.2/reference/program/mongo/#bin.mongo) shell的更多信息，例如连接到在不同主机和/或端口上运行的MongoDB实例，请参阅[mongo Shell](https://docs.mongodb.com/v4.2/mongo/)。

有关CRUD（创建，读取，更新，删除）操作的信息，请参阅

* [插入文档](https://docs.mongodb.com/v4.2/tutorial/insert-documents/)
* [查询文档](https://docs.mongodb.com/v4.2/tutorial/query-documents/)
* [更新文档](https://docs.mongodb.com/v4.2/tutorial/update-documents/)
* [删除文档](https://docs.mongodb.com/v4.2/tutorial/remove-documents/)

### 将社区版MongoDB作为Windows服务停止

要停止/暂停MongoDB服务，请使用服务控制台：

1. 在服务控制台中，找到MongoDB服务。
2. 右键单击MongoDB服务，然后单击“ **停止”**（或“ **暂停”**）。

### 将社区版MongoDB作为Windows服务删除

要删除MongoDB服务，请首先使用服务控制台停止该服务。然后以**管理员**身份打开[Windows命令提示符/解释器](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/cmd)（`cmd.exe`），然后运行以下命令：

复制

```
sc.exe delete MongoDB
```

## 从命令解释器运行MongoDB社区版

您可以从[Windows命令提示符/解释器](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/cmd)（`cmd.exe`）而不是作为服务运行MongoDB社区版。

以**管理员**身份打开[Windows命令提示符/解释器](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/cmd)（`cmd.exe`）。

重要

您必须以**管理员**身份打开命令解释器 。

### 1. 创建数据库目录。

创建MongoDB存储数据的[数据目录](https://docs.mongodb.com/v4.2/reference/glossary/#term-dbpath)。MongoDB的默认数据目录路径是 `\data\db` 启动MongoDB的驱动上的绝对路径 。

在**命令解释器中**，创建数据目录：

复制

```
cd C:\
md "\data\db"
```

### 2. 启动您的MongoDB数据库。

要启动MongoDB，请运行[`mongod.exe`](https://docs.mongodb.com/v4.2/reference/program/mongod.exe/#bin.mongod.exe)。

复制

```
"C:\Program Files\MongoDB\Server\4.2\bin\mongod.exe" --dbpath="c:\data\db"
```

该[`--dbpath`](https://docs.mongodb.com/v4.2/reference/program/mongod/#cmdoption-mongod-dbpath)选项指向您的数据库目录。

如果MongoDB数据库服务器正常运行，则 **命令解释器将**显示：

复制

```
[initandlisten] waiting for connections
```

重要

根据 Windows主机上的 [Windows Defender防火墙](https://docs.microsoft.com/en-us/windows/security/identity-protection/windows-firewall/windows-firewall-with-advanced-security)设置，Windows可能会显示“ \*\*安全警报”\*\*对话框，提示`C:\Program Files\MongoDB\Server\4.2\bin\mongod.exe`的“某些功能” 在网络上进行通信被阻止。要解决此问题：

1. 点击**专用网络，例如我的家庭或工作网络**。
2. 点击**允许访问**。

要了解有关安全性和MongoDB的更多信息，请参阅“ [安全性文档”](https://docs.mongodb.com/v4.2/security/)。

### 3. 连接到MongoDB。

要将[`mongo.exe`](https://docs.mongodb.com/v4.2/reference/program/mongo/#bin.mongo) shell 连接到MongoDB实例，请打开另一个 具有管理权限的**命令解释器**，然后运行：

复制

```
"C:\Program Files\MongoDB\Server\4.2\bin\mongo.exe"
```

有关连接[`mongo.exe`](https://docs.mongodb.com/v4.2/reference/program/mongo/#bin.mongo) shell 的更多信息，例如连接到在不同主机和/或端口上运行的MongoDB实例，请参阅[The mongo Shell](https://docs.mongodb.com/v4.2/mongo/)。

有关CRUD（创建，读取，更新，删除）操作的信息，请参阅：

* [插入文档](https://docs.mongodb.com/v4.2/tutorial/insert-documents/)
* [查询文档](https://docs.mongodb.com/v4.2/tutorial/query-documents/)
* [更新文档](https://docs.mongodb.com/v4.2/tutorial/update-documents/)
* [删除文档](https://docs.mongodb.com/v4.2/tutorial/remove-documents/)

## 其他注意事项

### 默认为localhost绑定

默认情况下，MongoDB在启动时将[`bindIp`](https://docs.mongodb.com/v4.2/reference/configuration-options/#net.bindIp)设置为 `127.0.0.1`，绑定到localhost网络接口。这意味着`mongod.exe`只能接受来自同一计算机上运行的客户端的连接。除非将此值设置为有效的网络接口，否则远程客户端将无法连接到`mongod.exe`，并且`mongod.exe`不能初始化[副本集](https://docs.mongodb.com/v4.2/reference/glossary/#term-replica-set)。

可以配置以下值：

* 在MongoDB配置文件中使用[`bindIp`](https://docs.mongodb.com/v4.2/reference/configuration-options/#net.bindIp)，或
* 通过命令行参数 [`--bind_ip`](https://docs.mongodb.com/v4.2/reference/program/mongod/#cmdoption-mongod-bind-ip)

警告

绑定到非本地主机（例如，可公共访问）的IP地址之前，请确保已保护群集免受未经授权的访问。有关安全建议的完整列表，请参阅“ [安全清单”](https://docs.mongodb.com/v4.2/administration/security-checklist/)。至少应考虑 [启用身份验证](https://docs.mongodb.com/v4.2/administration/security-checklist/#checklist-auth)并 [强化网络基础架构](https://docs.mongodb.com/v4.2/core/security-hardening/)。

有关配置[`bindIp`](https://docs.mongodb.com/v4.2/reference/configuration-options/#net.bindIp)的更多信息，请参见 [IP绑定](https://docs.mongodb.com/v4.2/core/security-mongodb-configuration/)。

### 版本发布和 `.msi`

如果您使用Windows安装程序（`.msi`） 安装了MongoDB，`.msi`将在其[发行系列](https://docs.mongodb.com/v4.2/reference/versioning/#release-version-numbers)（例如4.2.1到4.2.2）中自动升级。

升级完整版本系列（例如4.0至4.2）需要重新安装。

### 将MongoDB二进制文件添加到系统路径

本教程中的所有命令行示例均作为MongoDB二进制文件的绝对路径提供。您可以将`C:\Program Files\MongoDB\Server\4.2\bin`添加到系统路径中，然后省略MongoDB二进制文件的完整路径。

原文链接：<https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-windows/>

译者：汪子豪

update：小芒果


# 安装MongoDB企业版

这些文档提供了安装MongoDB企业版的说明。

MongoDB企业版可供MongoDB企业版订户使用，并包括其他一些功能，包括对SNMP监视，LDAP身份验证，Kerberos身份验证和系统事件审核的支持。

注意

由于[SERVER-29352](https://jira.mongodb.org/browse/SERVER-29352)，macOS上的MongoDB Enterprise \_不\_包括对SNMP的支持。

* [在Linux上安装](https://docs.mongodb.com/v4.2/administration/install-enterprise-linux/)

  在基于Linux的系统上安装MongoDB企业版的正式版本。
* [在macOS上安装](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-os-x/)

  在macOS上安装MongoDB企业版的正式版本
* [在Windows上安装](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-windows/)

  使用`.msi` 安装程序在Windows上安装MongoDB企业版。
* [使用Docker安装](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-with-docker/)

  安装MongoDB企业版Docker容器。

← [使用msiexec.exe在Windows上安装MongoDB社区](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-on-windows-unattended/)[在Linux上安装MongoDB Enterprise](https://docs.mongodb.com/v4.2/administration/install-enterprise-linux/) →

原文链接：<https://docs.mongodb.com/v4.2/administration/install-enterprise/>

译者：小芒果


# 在Linux上安装MongoDB企业版

此文档提供了为受支持的Linux系统安装MongoDB企业版的说明。

* [在Red Hat上安装](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-red-hat/)

  使用软件包在Red Hat Enterprise或CentOS系统上安装MongoDB企业版和必需的依赖项。
* [在Ubuntu上安装](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-ubuntu/)

  使用软件包在Ubuntu Linux系统上安装MongoDB企业版和必需的依赖项。
* [在Debian上安装](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-debian/)

  使用软件包在Debian Linux系统上安装MongoDB企业版和必需的依赖项。
* [在SUSE上安装](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-suse/)

  在SUSE Enterprise Linux上安装MongoDB企业版和必需的依赖项。
* [在亚马逊上安装](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-amazon/)

  在Amazon Linux AMI上安装MongoDB企业版和必需的依赖项。

原文链接：<https://docs.mongodb.com/v4.2/administration/install-enterprise-linux/>

译者：小芒果


# 在Mac OS安装MongoDB企业版

在本页面

* [概述](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-os-x/#overview)
* [注意事项](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-os-x/#considerations)
* [安装MongoDB企业版](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-os-x/#install-mongodb-enterprise-edition)
* [运行MongoDB企业版](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-os-x/#run-mongodb-enterprise-edition)
* [附加信息](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-os-x/#additional-information)

MONGODB ATLAS

[MongoDB Atlas](https://www.mongodb.com/cloud/atlas?tck=docs_server) 是MongoDB公司提供的MongoDB云服务，无需安装开销，并提供免费的入门套餐。

## 概述

使用本教程，可以使用下载的`.tgz`tarball 在macOS上手动安装MongoDB 4.2企业版 。

[MongoDB Enterprise Edition](https://www.mongodb.com/products/mongodb-enterprise-advanced?tck=docs_server) 在某些平台上可用，并且包含对与安全性和监视相关的多种功能的支持。

### MongoDB版本

本教程将安装MongoDB 4.2企业版。要安装其他版本的MongoDB企业版，请使用此页面左上角的版本下拉菜单选择该版本的文档。

## 注意事项

### 平台支持

MongoDB 4.2企业版支持macOS 10.12或更高版本。

有关更多信息，请参见[支持的平台](https://docs.mongodb.com/v4.2/administration/production-notes/#prod-notes-supported-platforms)。

### 生产注意事项

在生产环境中部署MongoDB之前，请考虑 [生产说明](https://docs.mongodb.com/v4.2/administration/production-notes/)文档，该文档提供了生产MongoDB部署的性能注意事项和配置建议。

## 安装MongoDB企业版

请按照以下步骤从 `.tgz`中手动安装MongoDB Enterprise Edition。

### 1. 下载压缩包。

从以下链接下载MongoDB企业版`tgz`tarball：

➤ [MongoDB的下载中心](https://www.mongodb.com/try/download/enterprise?tck=docs_server)

1. 在“ \*\*版本”\*\*下拉列表中，选择要下载的MongoDB版本。
2. 在**平台**下拉列表中，选择**macOS**。
3. 在**包**下拉列表中，选择**tgz**。
4. 点击**下载**。

### 2. 从下载的档案中提取文件。

复制

```
tar -zxvf mongodb-macos-x86_64-enterprise-4.2.8.tgz
```

如果您的网络浏览器在下载过程中自动将文件解压缩，则文件将以`.tar`结尾。

### 3. 确保二进制文件在`PATH`环境变量列出的目录中。

MongoDB二进制文件位于tarball`bin/`目录中。您可以：

* 将二进制文件复制到`PATH` 变量中列出的目录中，例如`/usr/local/bin`（根据需要更新 `/path/to/the/mongodb-directory/`安装目录）

  复制

  ```
  sudo cp /path/to/the/mongodb-directory/bin/* /usr/local/bin/
  ```
* 从`PATH`变量中列出的目录创建指向二进制文件的符号链接，例如`/usr/local/bin`（根据需要更新 `/path/to/the/mongodb-directory/`安装目录）：

  复制

  ```
  sudo ln -s  /path/to/the/mongodb-directory/bin/* /usr/local/bin/
  ```

## 运行MongoDB企业版

请按照以下步骤运行MongoDB企业版。这些说明假定您使用的是默认设置。

### 1. 创建数据目录。

首次启动MongoDB之前，必须创建该[`mongod`](https://docs.mongodb.com/v4.2/reference/program/mongod/#bin.mongod)进程将向其写入数据的目录。

例如，要创建`/usr/local/var/mongodb`目录：

复制

```
sudo mkdir -p /usr/local/var/mongodb
```

重要

从macOS 10.15 Catalina开始，Apple限制访问MongoDB默认`/data/db`数据目录。在macOS 10.15 Catalina上，您必须使用其他数据目录，例如 `/usr/local/var/mongodb`。

### 2. 创建日志目录。

您还必须创建该`mongod`进程将在其中写入其日志文件的目录：

例如，要创建`/usr/local/var/log/mongodb`目录：

复制

```
sudo mkdir -p /usr/local/var/log/mongodb
```

### 3. 设置数据和日志目录的权限。

确保正在运行的用户帐户[`mongod`](https://docs.mongodb.com/v4.2/reference/program/mongod/#bin.mongod)对这两个目录具有读写权限。如果您以自己的用户帐户运行[`mongod`](https://docs.mongodb.com/v4.2/reference/program/mongod/#bin.mongod)，并且刚刚在上面创建了两个目录，则用户应该已经可以访问它们。否则，您可以用`chown`来设置所有权，以替换适当的用户：

复制

```
sudo chown my_mongodb_user /usr/local/var/mongodb
sudo chown my_mongodb_user /usr/local/var/log/mongodb
```

### 4. 运行MongoDB。

要运行MongoDB，请在系统提示符下运行[`mongod`](https://docs.mongodb.com/v4.2/reference/program/mongod/#bin.mongod)过程，从上方提供`dbpath`和`logpath` 两个参数，并在后台`fork`该参数运行[`mongod`](https://docs.mongodb.com/v4.2/reference/program/mongod/#bin.mongod)。另外，您也可以选择在 [配置文件](https://docs.mongodb.com/v4.2/reference/configuration-options/)中存储`dbpath`，`logpath`，`fork`值和许多其他的参数。

#### 使用命令行参数运行`mongod`

在系统提示符下运行该[`mongod`](https://docs.mongodb.com/v4.2/reference/program/mongod/#bin.mongod)过程，直接在命令行上提供三个必需的参数：

复制

```
mongod --dbpath / usr / local / var / mongodb --logpath /usr/local/var/log/mongodb/mongo.log --fork
```

#### 使用配置文件运行`mongod`

在系统提示符下运行[`mongod`](https://docs.mongodb.com/v4.2/reference/program/mongod/#bin.mongod)过程，并使用`config`参数提供[配置文件](https://docs.mongodb.com/v4.2/reference/configuration-options/)的路径 ：

复制

```
mongod --config /usr/local/etc/mongod.conf
```

MACOS阻止`MONGOD`打开

`mongod`安装后，macOS可能无法运行。如果在启动时收到安全错误，`mongod` 显示无法识别或验证开发人员，请执行以下操作以授予`mongod`运行权限：

* 打开\_系统偏好设置\_
* 选择“ \_安全性和隐私”\_窗格。
* 在\_常规\_选项卡下，单击关于`mongod`消息右侧的按钮，根据您的macOS版本标记为“始终**打开”** 或“ **始终允许”**。

### 5. 验证MongoDB已成功启动。

验证MongoDB已成功启动：

复制

```
ps aux | grep -v grep | grep mongod
```

如果看不到`mongod`进程正在运行，请检查日志文件中是否有任何错误消息。

### 6. 开始使用MongoDB。

在相同的主机上启动[`mongo`](https://docs.mongodb.com/v4.2/reference/program/mongo/#bin.mongo) shell 作为[`mongod`](https://docs.mongodb.com/v4.2/reference/program/mongod/#bin.mongod)。您可以在不使用任何命令行选项的情况下运行[`mongo`](https://docs.mongodb.com/v4.2/reference/program/mongo/#bin.mongo) shell ，以使用默认端口\_27017\_连接到在\_本地主机\_上\_运行的\_[`mongod`](https://docs.mongodb.com/v4.2/reference/program/mongod/#bin.mongod)：

复制

```
mongo
```

* MACOS阻止`MONGOD`打开

  `mongod`安装后，macOS可能无法运行。如果在启动时收到安全错误，`mongod` 显示无法识别或验证开发人员，请执行以下操作以授予`mongod`运行权限：

  * 打开\_系统偏好设置\_
  * 选择“ \_安全性和隐私”\_窗格。
  * 在\_常规\_选项卡下，单击关于`mongod`消息右侧的按钮，根据您的macOS版本标记为“始终**打开”** 或“ **始终允许”**。

有关使用[`mongo`](https://docs.mongodb.com/v4.2/reference/program/mongo/#bin.mongo) shell 连接的更多信息，例如连接到[`mongod`](https://docs.mongodb.com/v4.2/reference/program/mongod/#bin.mongod)在其他主机和/或端口上运行的实例，请参阅[mongo Shell](https://docs.mongodb.com/v4.2/mongo/)。

为了帮助您开始使用MongoDB，MongoDB提供了各种驱动程序版本的[入门指南](https://docs.mongodb.com/v4.2/tutorial/getting-started/#getting-started)。有关可用版本，请参阅 [入门](https://docs.mongodb.com/v4.2/tutorial/getting-started/#getting-started)。

## 其他信息

### 默认为localhost绑定

默认情况下，MongoDB在启动时将[`bindIp`](https://docs.mongodb.com/v4.2/reference/configuration-options/#net.bindIp)设置为 `127.0.0.1`，该绑定到localhost网络接口。这意味着`mongod`只能接受来自同一计算机上运行的客户端的连接。除非将此值设置为有效的网络接口，否则远程客户端将无法连接到`mongod`，并且`mongod`不能初始化[副本集](https://docs.mongodb.com/v4.2/reference/glossary/#term-replica-set)。

可以配置以下值：

* 在MongoDB配置文件中使用[`bindIp`](https://docs.mongodb.com/v4.2/reference/configuration-options/#net.bindIp)，或
* 通过命令行参数 [`--bind_ip`](https://docs.mongodb.com/v4.2/reference/program/mongod/#cmdoption-mongod-bind-ip)

警告

绑定到非本地主机（例如，可公共访问）的IP地址之前，请确保已保护群集免受未经授权的访问。有关安全建议的完整列表，请参阅“ [安全清单”](https://docs.mongodb.com/v4.2/administration/security-checklist/)。至少应考虑 [启用身份验证](https://docs.mongodb.com/v4.2/administration/security-checklist/#checklist-auth)并 [强化网络基础架构](https://docs.mongodb.com/v4.2/core/security-hardening/)。

有关配置的更多信息[`bindIp`](https://docs.mongodb.com/v4.2/reference/configuration-options/#net.bindIp)，请参见 [IP绑定](https://docs.mongodb.com/v4.2/core/security-mongodb-configuration/)。

← [使用.tgz Tarball在Amazon Linux上安装MongoDB Enterprise](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-amazon-tarball/)\
[在Windows上安装MongoDB企业版](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-windows/) →

原文链接：<https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-os-x/>

译者：小芒果


# 在Windows安装MongoDB企业版

在本页面

* [概述](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-windows/#overview)
* [注意事项](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-windows/#considerations)
* [安装MongoDB企业版](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-windows/#install-mongodb-enterprise-edition)
* [从命令解释器启动MongoDB企业版](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-windows/#start-mongodb-enterprise-edition-from-the-command-interpreter)
* [将企业版MongoDB作为Windows服务启动](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-windows/#start-mongodb-enterprise-edition-as-a-windows-service)
* [将企业版MongoDB作为Windows服务停止](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-windows/#stop-mongodb-enterprise-edition-as-a-windows-service)
* [将企业版MongoDB作为Windows服务删除](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-windows/#remove-mongodb-enterprise-edition-as-a-windows-service)
* [其他注意事项](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-windows/#additional-considerations)

MONGODB ATLAS

[MongoDB Atlas](https://www.mongodb.com/cloud/atlas?tck=docs_server) 是MongoDB公司提供的MongoDB云服务，无需安装开销，并提供免费的入门套餐。

## 概述

使用本教程，可以使用默认安装向导在Windows上安装MongoDB 4.2企业版。

[MongoDB企业版](https://www.mongodb.com/products/mongodb-enterprise-advanced?tck=docs_server) 在某些平台上可用，并且包含对与安全性和监视相关的多种功能的支持。

### MongoDB版本

本教程将安装MongoDB 4.2企业版。要安装其他版本的MongoDB企业版，请使用此页面左上角的版本下拉菜单选择该版本的文档。

### 安装方法

本教程使用默认安装向导在Windows上安装MongoDB。或者，您可以选择使用`msiexec.exe`命令行（`cmd.exe`）以无人参与的方式在Windows上安装MongoDB 。这对于希望使用自动化部署MongoDB的系统管理员很有用。

➤有关说明，请参阅[使用msiexec.exe在Windows上安装MongoDB企业版](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-windows-unattended/) 。

## 注意事项

### 平台支持

MongoDB 4.2 Enterprise Edition 在[x86\_64](https://docs.mongodb.com/v4.2/administration/production-notes/#prod-notes-supported-platforms-x86-64)体系结构上支持Windows 的以下 **64位**版本 ：

* Windows Server 2019
* Windows 10 / Windows Server 2016
* Windows 8.1 / Windows Server 2012 R2
* Windows 8 / Windows Server 2012
* Windows 7 / Windows Server 2008 R2

MongoDB仅支持这些平台的64位版本。

有关更多信息，请参见[支持的平台](https://docs.mongodb.com/v4.2/administration/production-notes/#prod-notes-supported-platforms)。

### 生产注意事项

在生产环境中部署MongoDB之前，请考虑 [生产说明](https://docs.mongodb.com/v4.2/administration/production-notes/)文档，该文档提供了生产MongoDB部署的性能注意事项和配置建议。

## 安装MongoDB企业版

### 前提条件

Windows 10之前的Windows版本上的用户必须在安装MongoDB之前安装以下更新：

➤ [Windows系统Universal C运行时更新](https://support.microsoft.com/en-us/help/2999226/update-for-universal-c-runtime-in-windows)

Windows 10，Server 2016和Server 2019上的用户不需要此更新。

### 程序

请按照以下步骤使用Windows安装向导安装MongoDB Enterprise Edition。安装过程将同时安装MongoDB二进制文件和默认[配置文件](https://docs.mongodb.com/v4.2/reference/configuration-options/) `<install directory>\bin\mongod.cfg`。

#### 1. 下载安装程序。

从以下链接下载MongoDB社区安装程序`.msi`：

➤ [MongoDB的下载中心](https://www.mongodb.com/try/download/enterprise?tck=docs_server)

1. 在“ \*\*版本”\*\*下拉列表中，选择要下载的MongoDB版本。
2. 在**平台**下拉菜单中，选择**Windows**。
3. 在**Package**下拉列表中，选择**msi**。
4. 点击**下载**。

#### 3. 遵循MongoDB企业版安装向导。

该向导将引导您完成MongoDB和MongoDB Compass的安装。

1. * **选择安装类型**

     您可以选择“ **完整”**（建议大多数用户使用）或“ \*\*自定义”\*\*安装类型。“ **完整**设置”选项会将MongoDB和MongoDB工具安装到默认位置。使用“ **自定义** 安装”选项可以指定要安装的可执行文件以及安装位置。
2. * **服务配置**

     从MongoDB 4.0开始，您可以在安装过程中将MongoDB设置为Windows服务，也可以仅安装二进制文件。

     * MongoDB服务
     * MongoDB

     以下内容将MongoDB安装并配置为Windows服务。

     从MongoDB 4.0开始，您可以在安装过程中将MongoDB配置和启动为Windows服务，并在成功安装后启动MongoDB服务。 ![Image of the MongoDB Installer wizard - Service Configuration.](https://docs.mongodb.com/v4.2/_images/windows-installer.png)

     * 选择“ **将MongoD作为服务安装”**。
     * 选择以下任一项：
       * **以网络服务用户身份运行服务**（默认）

         这是Windows内置的Windows用户帐户

         **或者**
       * **以本地或域用户身份运行服务**
         * 对于现有的本地用户帐户，请为“ \*\*帐户域”\*\*指定一个句点（即`.`），并为该用户指定“ \*\*帐户名”\*\*和“ **帐户密码** ”。
         * 对于现有的域用户，请为该用户指定“ **帐户域”**，“ \*\*帐户名称”\*\*和“ **帐户密码** ”。
         * **服务名称**。指定服务名称。默认名称为`MongoDB`。如果您已经具有使用指定名称的服务，则必须选择另一个名称。
         * **数据目录**。指定数据目录，它对应于 [`--dbpath`](https://docs.mongodb.com/v4.2/reference/program/mongod/#cmdoption-mongod-dbpath)。如果目录不存在，安装程序将创建该目录并设置对服务用户的目录访问权限。
         * **日志目录**。指定日志目录，它对应于 [`--logpath`](https://docs.mongodb.com/v4.2/reference/program/mongod/#cmdoption-mongod-logpath)。如果目录不存在，安装程序将创建该目录并设置对服务用户的目录访问权限。
3. 对于Windows 8或更高版本，您可以让向导安装 [MongoDB Compass](https://www.mongodb.com/products/compass)。要安装Compass，请选择**Install MongoDB Compass**（默认）。注意安装脚本需要PowerShell 3.0或更高版本。如果您使用Windows 7，请取消单击 **Install MongoDB Compass**。您可以[从下载中心](https://www.mongodb.com/download-center/compass?tck=docs_server)手动[下载Compass](https://www.mongodb.com/download-center/compass?tck=docs_server)。 对于Windows 8或更高版本，您可以让向导安装 [MongoDB Compass](https://www.mongodb.com/products/compass)。要安装Compass，请选择**Install MongoDB Compass**（默认）。注意安装脚本需要PowerShell 3.0或更高版本。如果您使用Windows 7，请取消单击 **Install MongoDB Compass**。您可以[从下载中心](https://www.mongodb.com/download-center/compass?tck=docs_server)手动[下载Compass](https://www.mongodb.com/download-center/compass?tck=docs_server)。
4. 准备就绪后，点击**安装**。

### 2. 运行MongoDB安装程序。

例如，从Windows资源管理器/文件资源管理器中：

1. 转到下载MongoDB安装程序的目录（`.msi`文件）。默认情况下，这是您的`Downloads`目录。
2. 双击`.msi`文件。

### 如果您将MongoDB安装为Windows服务

成功安装后将启动MongoDB服务[\[1\]](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-windows/#cfg)。

要开始使用MongoDB，请将[`mongo.exe`](https://docs.mongodb.com/v4.2/reference/program/mongo/#bin.mongo) shell 连接到正在运行的MongoDB实例。要么：

* 在Windows资源管理器/文件资源管理器中，转到目录`C:\Program Files\MongoDB\Server\4.2\bin\`，然后单击\[`mongo.exe`] ([https://docs.mongodb.com/v4.2/reference/program/mongo/#bin.mongo)。](https://docs.mongodb.com/v4.2/reference/program/mongo/#bin.mongo%29。)
* 或者，使用管理权限打开**命令解释器**并运行：

  复制

  ```
  “ C：\ Program Files \ MongoDB \ Server \ 4.2 \ bin \ mongo.exe”
  ```

有关CRUD（创建，读取，更新，删除）操作的信息，请参阅：

* [插入文档](https://docs.mongodb.com/v4.2/tutorial/insert-documents/)
* [查询文档](https://docs.mongodb.com/v4.2/tutorial/query-documents/)
* [更新文档](https://docs.mongodb.com/v4.2/tutorial/update-documents/)
* [删除文档](https://docs.mongodb.com/v4.2/tutorial/remove-documents/)

|                                                                                            |                                      |
| ------------------------------------------------------------------------------------------ | ------------------------------------ |
| [\[1\]](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-windows/#id1) | 使用配置文件`\bin\mongod.cfg`配置MongoDB实例 。 |
|                                                                                            |                                      |

### 如果您没有将MongoDB安装为Windows服务

如果您仅安装了可执行文件而没有将MongoDB作为Windows服务安装，则必须手动启动MongoDB实例。

有关[启动](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-windows/#run-mongodb-enterprise-from-cmd) MongoDB实例的说明，请参阅[从命令解释器启动MongoDB企业版](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-windows/#run-mongodb-enterprise-from-cmd)。

## 从命令解释器启动MongoDB企业版

### 1. 创建数据库目录。

创建MongoDB存储数据的[数据目录](https://docs.mongodb.com/v4.2/reference/glossary/#term-dbpath)。MongoDB的默认数据目录路径`\data\db`是您从中启动MongoDB的驱动器上的绝对路径 。

在**命令解释器中**，创建数据目录：

复制

```
cd C:\
md "\data\db"
```

### 2. 启动您的MongoDB数据库。

要启动MongoDB，请运行[`mongod.exe`](https://docs.mongodb.com/v4.2/reference/program/mongod.exe/#bin.mongod.exe)。

复制

```
"C:\Program Files\MongoDB\Server\4.2\bin\mongod.exe" --dbpath="c:\data\db"
```

该[`--dbpath`](https://docs.mongodb.com/v4.2/reference/program/mongod/#cmdoption-mongod-dbpath)选项指向您的数据库目录。

如果MongoDB数据库服务器正常运行，则 **命令解释器将**显示：

复制

```
[initandlisten] waiting for connections
```

重要

根据 Windows主机上的 [Windows Defender防火墙](https://docs.microsoft.com/en-us/windows/security/identity-protection/windows-firewall/windows-firewall-with-advanced-security)设置，Windows可能会显示“ \*\*安全警报”\*\*对话框，显示`C:\Program Files\MongoDB\Server\4.2\bin\mongod.exe`的“某些功能” 在网络上进行通信被阻止。要解决此问题：

1. 点击**专用网络，例如我的家庭或工作网络**。
2. 点击**允许访问**。

要了解有关安全性和MongoDB的更多信息，请参阅“ [安全性文档”](https://docs.mongodb.com/v4.2/security/)。

### 3. 连接到MongoDB。

要将[`mongo.exe`](https://docs.mongodb.com/v4.2/reference/program/mongo/#bin.mongo)shell 连接到MongoDB实例，请打开另一个 具有管理权限的**命令解释器**，然后运行：

复制

```
"C:\Program Files\MongoDB\Server\4.2\bin\mongo.exe"
```

有关连接[`mongo.exe`](https://docs.mongodb.com/v4.2/reference/program/mongo/#bin.mongo) shell 的更多信息，例如连接到在其他主机和/或端口上运行的MongoDB实例，请参阅[mongo Shell](https://docs.mongodb.com/v4.2/mongo/)。

有关CRUD（创建，读取，更新，删除）操作的信息，请参阅：

* [插入文档](https://docs.mongodb.com/v4.2/tutorial/insert-documents/)
* [查询文档](https://docs.mongodb.com/v4.2/tutorial/query-documents/)
* [更新文档](https://docs.mongodb.com/v4.2/tutorial/update-documents/)
* [删除文档](https://docs.mongodb.com/v4.2/tutorial/remove-documents/)

## 将MongoDB企业版作为Windows服务启动

从版本4.0开始，您可以在安装过程中将MongoDB安装和配置为 **Windows服务**，并在成功安装后启动MongoDB服务。

要启动/重新启动MongoDB服务，请使用服务控制台：

1. 在服务控制台中，找到MongoDB服务。
2. 右键单击MongoDB服务，然后单击**启动**。

要开始使用MongoDB，请将[`mongo.exe`](https://docs.mongodb.com/v4.2/reference/program/mongo/#bin.mongo) shell 连接到正在运行的MongoDB实例。要进行连接，请打开具有管理权限的**命令解释器**并运行：

复制

```
"C:\Program Files\MongoDB\Server\4.2\bin\mongo.exe"
```

* 有关连接[`mongo.exe`](https://docs.mongodb.com/v4.2/reference/program/mongo/#bin.mongo) shell 的更多信息，例如连接到在其他主机和/或端口上运行的MongoDB实例，请参阅[mongo Shell](https://docs.mongodb.com/v4.2/mongo/)。

  有关CRUD（创建，读取，更新，删除）操作的信息，请参阅：

  * [插入文档](https://docs.mongodb.com/v4.2/tutorial/insert-documents/)
  * [查询文档](https://docs.mongodb.com/v4.2/tutorial/query-documents/)
  * [更新文档](https://docs.mongodb.com/v4.2/tutorial/update-documents/)
  * [删除文档](https://docs.mongodb.com/v4.2/tutorial/remove-documents/)

您也可以从命令行手动管理服务。要从命令行启动MongoDB服务，请以**管理员**身份打开[Windows命令提示符/解释器](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/cmd)（`cmd.exe`），然后运行以下命令：

### 1. 启动MongoDB服务。

关闭所有其他命令提示符，然后调用以下命令：

复制

```
net start MongoDB
```

### 2. 验证MongoDB已成功启动。

检查您的MongoDB日志文件是否存在以下行：

```
[initandlisten] waiting for connections on port 27017
```

您可能会在过程输出中看到非严重警告。只要您在MongoDB日志中看到此消息，就可以在对MongoDB进行初始评估时安全地忽略这些警告。

### 3. 连接到MongoDB服务器。

要通过[`mongo.exe`](https://docs.mongodb.com/v4.2/reference/program/mongo/#bin.mongo) shell 连接到MongoDB ，请打开另一个**Command Interpreter**。

复制

```
"C:\Program Files\MongoDB\Server\4.2\bin\mongo.exe"
```

## 将企业版MongoDB作为Windows服务停止

要停止/暂停MongoDB服务，请使用服务控制台：

1. 在服务控制台中，找到MongoDB服务。
2. 右键单击MongoDB服务，然后单击“ **停止”**（或“ **暂停”**）。

您也可以从命令行管理服务。要从命令行停止MongoDB服务，请以**管理员**身份打开[Windows命令提示符/解释器](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/cmd)（`cmd.exe`），然后运行以下命令：

复制

```
net stop MongoDB
```

## 将企业版MongoDB作为Windows服务删除

要删除MongoDB服务，请首先使用服务控制台停止该服务。然后以**管理员**身份打开[Windows命令提示符/解释器](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/cmd) （`cmd.exe`），然后运行以下命令：

复制

```
sc.exe delete MongoDB
```

## 其他注意事项

### 默认为localhost绑定

默认情况下，MongoDB在启动时将[`bindIp`](https://docs.mongodb.com/v4.2/reference/configuration-options/#net.bindIp)设置为 `127.0.0.1`，该绑定到localhost网络接口。这意味着`mongod.exe`只能接受来自同一计算机上运行的客户端的连接。除非将此值设置为有效的网络接口，否则远程客户端将无法连接到`mongod.exe`，并且`mongod.exe`不能初始化[副本集](https://docs.mongodb.com/v4.2/reference/glossary/#term-replica-set)。

可以配置以下值：

* 在MongoDB配置文件中使用[`bindIp`](https://docs.mongodb.com/v4.2/reference/configuration-options/#net.bindIp)，或
* 通过命令行参数 [`--bind_ip`](https://docs.mongodb.com/v4.2/reference/program/mongod/#cmdoption-mongod-bind-ip)

警告

绑定到非本地主机（例如，可公共访问）的IP地址之前，请确保已保护群集免受未经授权的访问。有关安全建议的完整列表，请参阅“ [安全清单”](https://docs.mongodb.com/v4.2/administration/security-checklist/)。至少应考虑 [启用身份验证](https://docs.mongodb.com/v4.2/administration/security-checklist/#checklist-auth)并 [强化网络基础架构](https://docs.mongodb.com/v4.2/core/security-hardening/)。

有关配置[`bindIp`](https://docs.mongodb.com/v4.2/reference/configuration-options/#net.bindIp)的更多信息，请参见 [IP绑定](https://docs.mongodb.com/v4.2/core/security-mongodb-configuration/)。

### 点发布和`.msi`

如果您使用Windows安装程序（`.msi`）安装了MongoDB ，它将`.msi`在其[发行系列](https://docs.mongodb.com/v4.2/reference/versioning/#release-version-numbers)（例如4.2.1到4.2.2）中自动升级。

升级完整版本系列（例如4.0至4.2）需要重新安装。

### 将MongoDB二进制文件添加到系统路径

本教程中的所有命令行示例均作为MongoDB二进制文件的绝对路径提供。您可以添加`C:\Program Files\MongoDB\Server\4.2\bin`到系统路径中，然后省略MongoDB二进制文件的完整路径。

原文链接：<https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-on-windows/>

译者：小芒果


# 使用Docker安装MongoDB企业版

重要

将容器与MongoDB结合使用的推荐解决方案是：

* 为了进行开发和测试，请使用 [MongoDB社区Docker容器](https://hub.docker.com/_/mongo/)。
* 对于MongoDB企业版生产安装，请通过[MongoDB Ops Manager](https://docs.opsmanager.mongodb.com/current/tutorial/install-k8s-operator)使用Kubernetes 。

注意

此过程使用Docker的官方[mongo image](https://github.com/docker-library/mongo)，该[镜像](https://github.com/docker-library/mongo)由Docker社区\_而非\_ MongoDB支持。

如果以上推荐的解决方案无法满足您的需求，请按照本教程中的步骤手动将Docker 安装到 [MongoDB企业版](https://www.mongodb.com/products/mongodb-enterprise-advanced?tck=docs_server)。

## 注意事项

[Docker](https://docs.docker.com/)的完整描述超出了本文档的范围。本页面假定您具有Docker的先验知识。

本文档仅描述了如何在Docker上安装MongoDB企业版，并且不会替换Docker上的其他资源。我们鼓励您在将Docker安装到MongoDB 企业版之前，彻底熟悉Docker及其相关主题。

重要

此过程使用Docker的官方[mongo image](https://github.com/docker-library/mongo)，该[镜像](https://github.com/docker-library/mongo)由Docker社区\_而非\_ MongoDB支持。它仅支持在其[存储库](https://github.com/docker-library/mongo)中列出的主要版本，只有每个主要版本有特定的次版本。次要版本可以在每个主要版本的文件夹中的`Dockerfile`中找到。

## 使用企业版MongoDB创建Docker镜像

### 1. 下载用于企业版MongoDB的Docker构建文件。

安装 [Docker](https://docs.docker.com/install/)并设置 [Docker Hub](https://hub.docker.com/)帐户后， 使用以下命令从[Docker Hub mongo项目](https://github.com/docker-library/mongo)下载构建文件 。设置`MONGODB_VERSION`为您选择的主要版本。

DOCKER HUB MONGO项目

MongoDB \_不\_维护Docker Hub mongo项目。任何支持请求都应发送给[Docker](https://github.com/docker-library/mongo)。

复制

```
export MONGODB_VERSION=4.0
curl -O --remote-name-all https://raw.githubusercontent.com/docker-library/mongo/master/$MONGODB_VERSION/{Dockerfile,docker-entrypoint.sh}
```

### 2. 构建Docker容器。

使用下载的构建文件来创建围绕企业版MongoDB的Docker容器镜像。将您的Docker Hub用户名设置为`DOCKER_USERNAME`。

复制

```
export DOCKER_USERNAME=username
chmod 755 ./docker-entrypoint.sh
docker build --build-arg MONGO_PACKAGE=mongodb-enterprise --build-arg MONGO_REPO=repo.mongodb.com -t $DOCKER_USERNAME/mongo-enterprise:$MONGODB_VERSION .
```

### 3. 测试您的镜像。

在Docker容器中本地运行mongod并检查版本，使用以下命令：

复制

```
docker run --name mymongo -itd $DOCKER_USERNAME/mongo-enterprise:$MONGODB_VERSION
docker exec -it mymongo /usr/bin/mongo --eval "db.version()"
```

这应该输出MongoDB的shell和服务器版本。

## 将镜像推送到Docker Hub

（可选）您可以将Docker镜像推送到远程存储库（例如Docker Hub），以在其他主机上使用该镜像。如果将镜像推送到Docker Hub，则可以在要通过Docker安装企业版MongoDB的每台主机上运行`docker pull`。有关使用`docker pull`的完整指导，请在[此处](https://docs.docker.com/engine/reference/commandline/pull/#examples)参考其文档 。

### 1. 检查您的本地镜像。

以下命令显示您的本地Docker镜像：

复制

```
docker images
```

您应该在命令输出中看到您的企业版MongoDB镜像。如果不这样做，请尝试[使用企业版MongoDB创建Docker镜像](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-with-docker/#create-docker-image-enterprise)。

### 2. 推送至Docker Hub。

将您的本地企业版MongoDB镜像推送到您的远程Docker Hub帐户。

复制

```
docker login
docker push $DOCKER_USERNAME/mongo-enterprise:$MONGODB_VERSION
```

如果您登录[Docker Hub](https://hub.docker.com/)站点，则应该看到存储库下面列出的镜像。

原文链接：<https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-with-docker/>

译者：小芒果


# 将社区版MongoDB升级到企业版MongoDB

MongoDB企业版提供了MongoDB社区版中未提供的各种功能，例如：

* [内存存储引擎](https://docs.mongodb.com/v4.2/core/inmemory/)
* [审计](https://docs.mongodb.com/v4.2/core/auditing/)
* [Kerberos身份验证](https://docs.mongodb.com/v4.2/core/kerberos/)
* [LDAP代理身份验证](https://docs.mongodb.com/v4.2/core/security-ldap/)和[ LDAP授权](https://docs.mongodb.com/v4.2/core/security-ldap-external/)
* [静态加密](https://docs.mongodb.com/v4.2/core/security-encryption-at-rest/)

本部分中的文档提供了从社区版MongoDB升级到企业版MongoDB的说明。

重要

不要使用这些说明升级到另一个发行版本。要升级发行版本，请参阅相应的发行升级说明，例如[Upgrade to MongoDB 4.2](https://docs.mongodb.com/v4.2/release-notes/4.2/#upgrade)。

| 部署方式 | 教程                                                                                                           |
| ---- | ------------------------------------------------------------------------------------------------------------ |
| 单节点  | [升级到MongoDB Enterprise（单节点）](https://docs.mongodb.com/v4.2/tutorial/upgrade-to-enterprise-standalone/)       |
| 副本集  | [升级到MongoDB Enterprise（副本集）](https://docs.mongodb.com/v4.2/tutorial/upgrade-to-enterprise-replica-set/)      |
| 分片集群 | [升级到MongoDB Enterprise（分片集群）](https://docs.mongodb.com/v4.2/tutorial/upgrade-to-enterprise-sharded-cluster/) |

← [使用Docker安装企业版MongoDB](https://docs.mongodb.com/v4.2/tutorial/install-mongodb-enterprise-with-docker/)\
[升级到企业版MongoDB（单节点）](https://docs.mongodb.com/v4.2/tutorial/upgrade-to-enterprise-standalone/) →

原文链接：<https://docs.mongodb.com/v4.2/administration/upgrade-community-to-enterprise/>

译者：小芒果


# 验证MongoDB软件包的完整性

在本页面

* [验证Linux / macOS软件包](https://docs.mongodb.com/v4.2/tutorial/verify-mongodb-packages/#verify-linux-macos-packages)
* [验证Windows软件包](https://docs.mongodb.com/v4.2/tutorial/verify-mongodb-packages/#verify-windows-packages)

MongoDB版本团队对所有软件包进行数字签名，以证明特定的MongoDB软件包是有效且未更改的MongoDB版本。在安装MongoDB之前，您应该使用提供的PGP签名或SHA-256校验和来验证软件包。

通过检查文件的真实性和完整性以防止篡改，PGP签名提供了最有力的保证。

加密校验和仅验证文件完整性以防止网络传输错误。

## 验证的Linux / MacOS的包

### 使用PGP / GPG

MongoDB使用不同的PGP密钥在每个发行分支上签名。自MongoDB 2.2起，每个发行分支的公钥文件都可以从[密钥服务器](https://www.mongodb.org/static/pgp/) 以文本`.asc`和二进制`.pub`格式下载。

### 1. 下载MongoDB安装文件。

根据您的环境从[MongoDB下载中心](https://www.mongodb.com/try/download?tck=docs_server)下载二进制文件。

例如，要通过shell下载macOS`4.2.8`发行版，请运行以下命令：

复制

```
curl -LO https://fastdl.mongodb.org/osx/mongodb-macos-x86_64-4.2.8.tgz
```

### 2. 下载公共签名文件。

复制

```
curl -LO https://fastdl.mongodb.org/osx/mongodb-macos-x86_64-4.2.8.tgz.sig
```

### 3. 下载然后导入密钥文件。

如果尚未下载并导入MongoDB 4.2公钥，请运行以下命令：

复制

```
curl -LO https://www.mongodb.org/static/pgp/server-4.2.asc
gpg --import server-4.2.asc
```

PGP应该返回以下响应：

复制

```
gpg: key 4B7C549A058F8B6B: "MongoDB 4.2 Release Signing Key <packaging@mongodb.com>" imported
gpg: Total number processed: 1
gpg:               imported: 1
```

### 4. 验证MongoDB安装文件。

运行以下命令：

复制

```
gpg --verify mongodb-macos-x86_64-4.2.8.tgz.sig mongodb-macos-x86_64-4.2.8.tgz
```

GPG应该返回以下响应：

复制

```
gpg: Signature made Wed Jun  5 03:17:20 2019 EDT
gpg:                using RSA key 4B7C549A058F8B6B
gpg: Good signature from "MongoDB 4.2 Release Signing Key <packaging@mongodb.com>" [unknown]
```

如果软件包已正确签名，但是您当前不信任本地密钥`trustdb`，`gpg`则还会返回以下消息：

复制

```
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: E162 F504 A20C DF15 827F  718D 4B7C 549A 058F 8B6B
```

如果您收到以下错误消息，请确认您导入了正确的公钥：

复制

```
gpg: Can't check signature: public key not found
```

### 使用SHA-256

### 1. 下载MongoDB安装文件。

根据您的环境从[MongoDB下载中心](https://www.mongodb.com/try/download?tck=docs_server)下载二进制文件。

例如，要通过shell下载macOS`4.2.8`发行版，请输入以下命令：

复制

```
curl -LO https://fastdl.mongodb.org/osx/mongodb-macos-x86_64-4.2.8.tgz
```

### 2. 下载SHA256文件。

复制

```
curl -LO https://fastdl.mongodb.org/osx/mongodb-macos-x86_64-4.2.8.tgz.sha256
```

### 3. 使用SHA-256校验和验证MongoDB软件包文件。

计算软件包文件的校验和：

复制

```
shasum -c mongodb-macos-x86_64-4.2.8.tgz.sha256
```

如果校验和与下载的软件包匹配，它将返回以下内容：

复制

```
mongodb-macos-x86_64-4.2.8.tgz: OK
```

## 验证Windows软件包

这将根据其SHA256密钥验证MongoDB二进制文件。

### 1. 下载安装程序。

下载MongoDB `.msi`安装程序。例如，要下载最新版本的社区版MongoDB：

➤ [MongoDB社区版下载中心](https://www.mongodb.com/try/download/community?tck=docs_server)

1. 在**版本**下拉列表中，选择 `4.2.8 (current release)`。
2. 在**平台**下拉菜单中，选择**Windows**。
3. 在**Package**下拉列表中，选择**msi**。
4. 单击\*\*下载，\*\*然后将文件保存到下载文件夹中。

### 2. 获取公共签名文件。

获取您的MongoDB版本的公共签名文件。

例如，对于最新版本社区版MongoDB的SHA256签名：

1. 从<https://fastdl.mongodb.org/win32/mongodb-win32-x86_64-2012plus-4.2.8-signed.msi.sha256复制内容。>
2. 将内容保存到“ `mongodb-win32-x86_64-2012plus-4.2.8-signed.msi.sha256`”下载文件中的文件夹中。

### 3. 将签名文件与MongoDB installer hash进行比较。

要将签名文件与MongoDB二进制文件的哈希值进行比较，请调用以下Powershell脚本：

复制

```
$sigHash = (Get-Content $Env:HomePath\Downloads\mongodb-win32-x86_64-2012plus-4.2.8-signed.msi.sha256 | Out-String).SubString(0,64).ToUpper(); `
$fileHash = (Get-FileHash $Env:HomePath\Downloads\mongodb-win32-x86_64-2012plus-4.2.8-signed.msi).Hash.Trim(); `
echo $sigHash; echo $fileHash; `
$sigHash -eq $fileHash
```

复制

```
AF5AF79EFE540DCDDC2825A396C71FCFC4FEB463BC9CADDCCDE20AD126321CCC
AF5AF79EFE540DCDDC2825A396C71FCFC4FEB463BC9CADDCCDE20AD126321CCC
True
```

该命令输出三行：

* 您直接从MongoDB下载的`SHA256`哈希。
* 一个你从MongoDB下载的MongoDB二进制计算`SHA256`哈希值。
* 一个取决于哈希匹配的`True`或者`False`结果。

如果哈希匹配，则将验证MongoDB二进制文件。

← [升级到MongoDB企业版（分片集群）](https://docs.mongodb.com/v4.2/tutorial/upgrade-to-enterprise-sharded-cluster/)\
[The mongo Shell](https://docs.mongodb.com/v4.2/mongo/) →

原文链接：<https://docs.mongodb.com/v4.2/tutorial/verify-mongodb-packages/>

译者：小芒果


# The mongo Shell

**在本页面**

* [启动mongo Shell并连接到MongoDB](#启动连接)
* [使用mongo Shell](#使用mongo-Shell)
* [制表符完成和其他键盘快捷键](#制表符完成和其他键盘快捷键)
* [mongorc.js文件](#mongorcjs文件)
* [退出Shell](#退出Shell)

mongo shell是MongoDB的交互式JavaScript接口。您可以使用mongo shell查询和更新数据以及执行管理操作。 mongo shell作为MongoDB Server安装的一部分包含在内。 MongoDB还提供mongo shell作为独立软件包。如何下载独立的mongo shell软件包： 1.打开下载中心。对于mongo Enterprise Shell，选择MongoDB Enterprise Server选项卡。 2.从下拉列表中选择您的首选版本和操作系统。 3.选择要根据您的系统下载的安装包：

| 系统    | 下载包                         |
| ----- | --------------------------- |
| Win   | 选择ZIP以下载包含mongo shell的安装包   |
| Mac   | 选择TGZ以下载包含mongo shell的安装包   |
| Linux | 选择shell以下载包含mongo shell的安装包 |

安装并启动MongoDB之后，将mongo shell连接到正在运行的MongoDB实例。

## 启动mongo Shell并连接到MongoDB

> **前提条件**
>
> 在尝试启动mongo shell之前，请确保MongoDB正在运行。

打开终端窗口（或Windows的命令提示符），然后转`<mongodb安装目录>/bin` 目录。

```
cd <mongodb安装目录>/bin
```

> **\[success] Note**
>
> 将`<mongodb安装目录> / bin`添加到PATH环境变量中，可以键入mongo，而不必转到`<mongodb安装目录> / bin`目录或指定二进制文件的完整路径。

#### **默认端口上的本地MongoDB实例**

您可以在不使用任何命令行选项的情况下运行mongo shell，以使用默认端口27017连接到在本地主机上运行的MongoDB实例：

```
mongo
```

#### **非默认端口上的本地MongoDB实例**

要显式指定端口，请包括--port命令行选项。例如，要使用非默认端口28015连接到在localhost上运行的MongoDB实例，请执行以下操作：

#### **非默认端口上的本地MongoDB实例**

要显式指定端口，请包括--port命令行选项。例如，要使用非默认端口28015连接到在localhost上运行的MongoDB实例，请执行以下操作：

```
mongo --port 28015
```

#### **远程主机上的MongoDB实例**

要明确指定主机名或端口：

* 您可以指定一个[连接字符串](https://docs.mongodb.com/master/reference/connection-string/)。例如：要连接到在远程主机上运行的MongoDB实例，请执行以下操作：

```
mongo "mongodb://mongodb0.example.com:28015"
```

* 您可以使用命令行选项[--host <`host`>:<`port`>](https://docs.mongodb.com/manual/reference/program/mongo/#cmdoption-mongo-host)。例如，要连接到在远程主机上运行的MongoDB实例，请执行以下操作：

```
mongo --host mongodb0.example.com:28015
```

您可以使用[`--host`<`host`>](https://docs.mongodb.com/master/reference/program/mongo/#cmdoption-mongo-host)和[`--port` <`port`>](https://docs.mongodb.com/master/reference/program/mongo/#cmdoption-mongo-port) 命令行选项。例如，要连接到在远程主机上运行的MongoDB实例，请执行以下操作：

```
mongo --host mongodb0.example.com --port 28015
```

#### **具有身份验证的MongoDB实例**

要连接到MongoDB实例，需要进行身份验证：

您可以在连接字符串中指定用户名，身份验证数据库以及可选的密码。例如：以**alice**用户身份连接并认证到远程MongoDB实例：

> **\[success] Note**
>
> 如果未在连接字符串中指定密码，则shell程序将提示您输入密码。

```
mongo "mongodb://alice@mongodb0.examples.com:28015/?authSource=admin"
```

您可以使用[`--username`<`user`>](https://docs.mongodb.com/master/reference/program/mongo/#cmdoption-mongo-username) 和[`--password`](https://docs.mongodb.com/master/reference/program/mongo/#cmdoption-mongo-password), [`--authenticationDatabase <db>`](https://docs.mongodb.com/master/reference/program/mongo/#cmdoption-mongo-authenticationdatabase)命令行选项。 例如，以**alice**用户身份连接并认证到远程MongoDB实例：

> **\[success] Note**
>
> 如果您指定\*\*--password\*\*而不输入用户密码，则shell程序将提示您输入密码。

```
mongo --username alice --password --authenticationDatabase admin --host mongodb0.examples.com --port 28015
```

#### 连接到MongoDB复制集

要连接到复制集：

* 您可以在连接字符串中指定复制集名称和成员

```
mongo "mongodb://mongodb0.example.com.local:27017,mongodb1.example.com.local:27017,mongodb2.example.com.local:27017/?replicaSet=replA"
```

* 如果使用[DNS Seedlist 链接格式](https://docs.mongodb.com/master/reference/connection-string/#connections-dns-seedlist)，则可以指定连接字符串：

```
mongo "mongodb+srv://server.example.com/"
```

> **\[success] Note**
>
> 对于连接，使用\*\*+ srv\*\*连接字符串修饰符会自动将ssl选项设置为true。

* 您可以从 [--host `<replica set name>/<host1>:<port1>,<host2>:<port2>`,... ](https://docs.mongodb.com/master/reference/program/mongo/#cmdoption-mongo-host)命令行选项中指定复制集名称和成员。 例如，要连接到名为**replA**的复制集，请执行以下操作：

```
mongo --host replA/mongodb0.example.com.local:27017,mongodb1.example.com.local:27017,mongodb2.example.com.local:27017
```

#### **TLS/SSL 连接**

关于TLS/SS连接：

* 您可以在[连接字符串](https://docs.mongodb.com/master/reference/connection-string/)中指定**ssl = true**选项。

```
mongo "mongodb://mongodb0.example.com.local:27017,mongodb1.example.com.local:27017,mongodb2.example.com.local:27017/?replicaSet=replA&ssl=true"
```

* 如果使用[DNS Seedlist 链接格式](https://docs.mongodb.com/master/reference/connection-string/#connections-dns-seedlist)，则可以包括\*\*+srv\*\*连接字符串修饰符：

```
mongo "mongodb+srv://server.example.com/"
```

> **\[success] Note**
>
> 对于连接，使用\*\*+srv\*\*连接字符串修饰符会自动将ssl选项设置为true。

* 您可以指定[`--ssl`](https://docs.mongodb.com/master/reference/program/mongo/#cmdoption-mongo-ssl)命令行选项。 例如，要连接到名为**replA**的复制集，请执行以下操作：

```
mongo --ssl --host replA/mongodb0.example.com.local:27017,mongodb1.example.com.local:27017,mongodb2.example.com.local:27017
```

另：有关连接示例中使用的选项以及其他选项的更多信息，请参阅([mongo参考](https://docs.mongodb.com/manual/reference/program/mongo/)和 [启动mongo的示例](https://docs.mongodb.com/manual/reference/program/mongo/#mongo-usage-examples))。

## 使用mongoShell

要显示您正在使用的数据库，请键入**db**：

```
db
```

该操作应返回**test** 数据库名，这是默认数据库。 要切换数据库，请发出\*\*use <`db`>\*\*帮助器，如以下示例所示：

```
use <database>
```

另请参见[`db.getSiblingDB()`](https://docs.mongodb.com/master/reference/method/db.getSiblingDB/#db.getSiblingDB)方法，以从当前数据库访问其他数据库，而无需切换当前数库上下文（即**db**）。\
要列出用户可用的数据库，可使用：**show dbs** <显示用户列表里所有数据库>

您可以切换到不存在的数据库。首次将数据存储在数据库中（例如通过创建集合）时，MongoDB会创建数据库。 例如，以下代码在insertOne（）操作期间创建数据库**myNewDatabase**和[集合](https://docs.mongodb.com/master/reference/glossary/#term-collection) **myCollection**：

```
use myNewDatabase
db.myCollection.insertOne( { x: 1 } );
```

是mongo shell中可用的方法之一。

* **db**是指当前数据库。
* **myCollection**是集合的名称。

  如果[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell不接受集合的名称，则可以使用替代的 [`db.getCollection()`](https://docs.mongodb.com/master/reference/method/db.getCollection/#db.getCollection)语法。例如，如果集合名称包含空格或连字符，以数字开头或与内置函数冲突：

```
db.getCollection("3 test").find()
db.getCollection("3-test").find()
db.getCollection("stats").find()
```

[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell提示符每行的限制为4095个字符（code points）。 如果您输入的行中包含4095个以上的字符（code points），则Shell将截断它。 有关mongo shell中MongoDB基本操作的更多文档，请参阅：

* [Getting Started Guide](https://docs.mongodb.com/getting-started/shell)
* [Insert Documents](https://docs.mongodb.com/manual/tutorial/insert-documents/)
* [Query Documents](https://docs.mongodb.com/manual/tutorial/query-documents/)
* [Update Documents](https://docs.mongodb.com/manual/tutorial/update-documents/)
* [Delete Documents](https://docs.mongodb.com/manual/tutorial/remove-documents/)
* [mongo Shell Methods](https://docs.mongodb.com/manual/reference/method/)

如果部署使用访问控制运行，则该操作将根据用户权限返回不同的值。 有关详细信息，请参见[listDatabases Behavior](https://docs.mongodb.com/manual/reference/command/listDatabases/#listdatabases-behavior)。

### **格式化打印结果**

`db.collection.find()`方法是用于从集合中检索文档的JavaScript方法。 `db.collection.find()`方法将游标返回到结果。 但是，在mongo shell中，如果未使用**var**关键字将返回的游标分配给变量，则该游标会自动迭代最多20次，来打印与查询匹配的前20个文档。 mongo shell将提示 输入`it`以使其再次迭代20次。

要格式化打印结果，可以将`.pretty()`添加到操作中，如下所示：

```
db.myCollection.find().pretty()
```

此外，您可以在mongo shell中使用以下显式打印方法：

* print() to print without formatting
* print(tojson()) to print with [JSON](https://docs.mongodb.com/manual/reference/glossary/#term-json) formatting and equivalent to printjson()
* printjson() to print with [JSON](https://docs.mongodb.com/manual/reference/glossary/#term-json) formatting and equivalent to print(tojson())

有关在mongo shell中处理光标的更多信息和示例，请参阅[terate a Cursor in the mongo](https://docs.mongodb.com/manual/tutorial/iterate-a-cursor/)。 另请参阅[Cursor Help](https://docs.mongodb.com/manual/tutorial/access-mongo-shell-help/#mongo-shell-help-cursor) ，以获取mongo shell中的游标帮助列表。

### mongo Shell中的多行操作

如果您以开括号（'（'），大括号（'{'）或开括号（'\['）结束一行，则后续行以省略号（“ ...”）开头，直到您 输入相应的右括号（'）'，右括号（'}'）或右括号（']'）。 mongo shell在评估代码之前等待右括号，右括号或右括号，如以下示例所示：

```
>if ( x > 0 ) {
... count++;
... print (x);
... }
```

如果输入两个空行，则可以退出行继续模式，如以下示例所示：

```
> if (x > 0
...
...
>
```

## 制表符完成和其他键盘快捷键

shell支持键盘快捷键。 例如：

* 使用向上/向下箭头键滚动浏览命令历史记录。有关.dbshell文件的更多信息，请参见[.dbshell](https://docs.mongodb.com/manual/reference/program/mongo/#mongo-dbshell-file) 文档。
* 使用<`Tab`>来自动完成或列出完成可能性，如以下示例中所示，该示例使用<`Tab`>来完成以字母'c'开头的方法名称：

```
db.myCollection.c<Tab>
```

因为有许多以字母'**c**'开头的收集方法，所以<`Tab`>将列出以\*\*'c'\*\*开头的各种方法。\
有关快捷键的完整列表，请参见：Shell 快捷命令（[Shell Keyboard Shortcuts](https://docs.mongodb.com/manual/reference/program/mongo/#mongo-keyboard-shortcuts)）。

## mongorc.js文件

启动时，mongo将在用户的HOME目录中检查名为`.mongorc.js`的JavaScript文件。 如果找到，mongo会在首次显示提示之前解释`.mongorc.js`的内容。如果您使用舍shell程序来评估JavaScript文件或表达式，或者通过在命令行上使用--eval选项，或者通过将.js文件指定给mongo，则mongo将在JavaScript完成处理后读取`.mongorc.js`文件。 您可以使用--norc选项防止加载`.mongorc.js`。

## 退出Shell

要退出shell，请键入`quit（）`或使用 `<Ctrl-C>`快捷方式。

另可参考：

* [Getting Started Guide](https://docs.mongodb.com/getting-started/shell)
* [mongo](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo) Reference Page

译者：王恒 金江

### MongoDB中文社区

![MongoDB中文社区—MongoDB爱好者技术交流平台](https://mongoing.com/wp-content/uploads/2020/09/6de8a4680ef684d-2.png)

| 资源列表推荐             | 资源入口                                                                                                                                                                                                                                                                       |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| MongoDB中文社区官网      | <https://mongoing.com/>                                                                                                                                                                                                                                                    |
| 微信服务号 ——最新资讯和优质文章  | Mongoing中文社区（mongoing-mongoing）                                                                                                                                                                                                                                            |
| 微信订阅号 ——发布文档翻译内容   | MongoDB中文用户组（mongoing123）                                                                                                                                                                                                                                                  |
| 官方微信号 —— 官方最新资讯    | MongoDB数据库（MongoDB-China）                                                                                                                                                                                                                                                  |
| MongoDB中文社区组委会成员介绍 | <https://mongoing.com/core-team-members>                                                                                                                                                                                                                                   |
| MongoDB中文社区翻译小组介绍  | <https://mongoing.com/translators>                                                                                                                                                                                                                                         |
| MongoDB中文社区微信技术交流群 | 添加社区助理小芒果微信（ID:mongoingcom），并备注 mongo                                                                                                                                                                                                                                      |
| MongoDB中文社区会议及文档资源 | <https://mongoing.com/resources>                                                                                                                                                                                                                                           |
| MongoDB中文社区大咖博客    | [基础知识](https://mongoing.com/basic-knowledge) [性能优化](https://mongoing.com/performance-optimization) [原理解读](https://mongoing.com/interpretation-of-principles) [运维监控](https://mongoing.com/operation-and-maintenance-monitoring) [最佳实践](https://mongoing.com/best-practices) |
| MongoDB白皮书         | <https://mongoing.com/mongodb-download-white-paper>                                                                                                                                                                                                                        |
| MongoDB初学者教程-7天入门  | <https://mongoing.com/mongodb-beginner-tutorial>                                                                                                                                                                                                                           |
| 社区活动邮件订阅           | <https://sourl.cn/spszjN>                                                                                                                                                                                                                                                  |


# 配置mongo Shell

**在本页面**

* [自定义提示](#自定义)
* [在mongo shell中使用外部编辑器](#外部编辑器)
* [改变mongo shell(batchSize)](#changeSize)

> **\[success] Note**
>
> 下面的文档是[MongoDB服务器下载](https://www.mongodb.com/try/download/community?tck=docs_server).中包含的[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell。有关新的MongoDB Shell ，**mongosh**的信息，请参考[mongosh文档](https://docs.mongodb.com/mongodb-shell/)。
>
> 要了解这两种shell的区别，请参阅[Comparison of the mongo Shell and mongosh](https://docs.mongodb.com/master/mongo/#compare-mongosh-mongo).

## 自定义提示

您可以通过在 [`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell中设置变量**prompt**来修改提示符的内容。**prompt**变量可以保存字符串和JavaScript代码。如果**prompt**包含一个返回字符串的函数，[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) 可以在每个提示符中显示动态信息。

您可以在[`.mongorc.js`](https://docs.mongodb.com/master/reference/program/mongo/#mongo-mongorc-file) 文件中添加提示逻辑，以在每次启动[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell时设置提示。

### **自定义提示以显示操作数**

例如，要使用当前会话中发出的操作数创建[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell提示，请在[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell中定义以下变量：

```
cmdCount = 1;
prompt = function() {
             return (cmdCount++) + "> ";
         }
```

提示将展示类似于以下内容：

```
1>
2>
3>
```

### 自定义提示以显示数据库和主机名

要以`<database> @ <hostname> $`的形式创建[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell\`提示，请定义以下变量：

```
host = db.serverStatus().host;

prompt = function() {
             return db+"@"+host+"$ ";
         }
```

提示将类似于以下内容：

```
test@myHost1$
```

### 自定义提示以显示时间和文档计数

要创建一个包含系统正常运行时间和当前数据库中文档数的[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell提示，请在[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell中定义以下提示变量：

```java
prompt = function(){
    return "Uptime:"+db.serverStatus().uptime+" Documents:"+db.stats().objects+" > "; }
```

提示符将类似于以下内容：

```
Uptime:5897 Documents:6 >
```

## 在mongo shell中使用外部编辑器

您可以通过在启动[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell之前设置[`EDITOR`](https://docs.mongodb.com/master/reference/program/mongo/#envvar-EDITOR) 环境变量，这样就可以在 [`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell中使用自己的编辑器。

```
export EDITOR=vim
mongo
```

进入[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell`后，您可以通过输入`\*\*edit <`variable`>**或**edit <`function`>\*\*使用指定的编辑器进行编辑，如以下示例所示：\
1.定义一个函数`myFunction`：

```java
function myFunction () { }
```

2.使用编辑器编辑函数：

```
edit myFunction
```

该命令将打开`vim`编辑会话。 完成编辑后，保存并退出`vim`编辑会话。\
3.在[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell中，键入`myFunction`以查看函数定义：

```
myFunction
```

展示的是已经保存编辑后的结果:

```java
function myFunction() { 
    print("This was edited");
}
```

> **\[success] Note**
>
> 当mongo shell解释在外部编辑器中编辑的代码时，它可能会修改函数中的代码，具体取决于JavaScript编译器。 例如，mongo可以将**1 + 1**转换为2或删除注释。 实际更改仅影响代码的外观，并且会根据所使用的JavaScript版本而有所不同，但不会影响代码的语义。

## 改变mongo shell(batchSize)

[`db.collection.find()`](https://docs.mongodb.com/master/reference/method/db.collection.find/#db.collection.find)方法是用于从集合中检索文档的JavaScript方法。[`db.collection.find()`](https://docs.mongodb.com/master/reference/method/db.collection.find/#db.collection.find)方法将游标返回到结果。 但是，在mongo shell中，如果未使用**var**关键字将返回的游标分配给变量，则该游标会自动迭代最多20次，来打印与查询匹配的前20个文档。 mongo shell将提示 输入`it`以使其再次迭代20次。 您可以设置`DBQuery.shellBatchSize`属性，以更改文档数默认值**20**，如以下示例中将其设置为**10**：

```
DBQuery.shellBatchSize = 10;
```

译者：王恒 金江

校对：杨帅


# 使用 mongo Shell帮助

**在本页面**

* [命令行帮助](#命令行)
* [shell帮助](#shell)
* [数据库帮助](#数据库)
* [表级别帮助](#收集)
* [游标级别帮助](#光标)
* [包装对象帮助](#包装对象)

> **\[success] Note**
>
> 下面的文档是[MongoDB服务器下载](https://www.mongodb.com/try/download/community?tck=docs_server).中包含的[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell。有关新的MongoDB Shell ，**mongosh**的信息，请参考[mongosh文档](https://docs.mongodb.com/mongodb-shell/)。
>
> 要了解这两种shell的区别，请参阅[Comparison of the mongo Shell and mongosh](https://docs.mongodb.com/master/mongo/#compare-mongosh-mongo).

除了《 MongoDB中文手册》中的文档外，[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell在其“在线”帮助系统中提供了一些其他信息。 本文档概述了访问此帮助信息的过程。

## **命令行帮助**

要查看选项列表和启动[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell相关的帮助，请从命令行使用[`--help`](https://docs.mongodb.com/master/reference/program/mongo/#cmdoption-mongo-help)选项：

```
mongo --help
```

## **Shell帮助**

当需要查看帮助列表时，请在[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo)shell中键入`help` ：

```
help
```

## **数据库帮助**

在[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell中：

* 当需要查看服务器上的数据库列表，请使用**show dbs**命令：

```
show dbs
```

**`show database`是`show dbs`的别名**

* 当需要查看可在db对象上使用的方法的帮助列表，请调用[`db.help()`](https://docs.mongodb.com/master/reference/method/db.help/#db.help)方法：

```
db.help()
```

* 当需要查看在 `shell`中查看某些方法的具体实现，请键入不带括号(())的`db.<method name>`，如以下示例所示，它将返回方法[`db.updateUser()`](https://docs.mongodb.com/master/reference/method/db.updateUser/#db.updateUser)的实现：

```
db.updateUser
```

如果部署使用访问控制运行，则该操作将根据用户权限返回不同的值。 有关详细信息，请参见listDatabases行为。

## **表级别帮助**

在[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell中：

* 要查看当前数据库中的集合列表，请使用**show collections**命令：

```
show collections
```

另可参考：[show collections](https://docs.mongodb.com/manual/release-notes/4.0-compatibility/#compat-show-collections)

* 要查看收集对象上可用方法的帮助（例如`db.<collection>`），请使用`db.<collection>.help()`方法：

```
db.collection.help()
```

`<collection>`可以是存在的集合的名称，尽管您可以指定不存在的集合。

* 要查看收集方法的实现，请键入不带括号(())的`db.<collection>.<method>`名称，如以下示例所示，它将返回[`save()`](https://docs.mongodb.com/master/reference/method/db.collection.save/#db.collection.save)方法的实现：

```
db.collection.save
```

## **游标相关帮助**

在mongo shell中使用`find()`方法执行读取操作时，可以使用各种游标方法来修改`find()`行为，并可以使用各种JavaScript方法来处理从`find()`方法返回的游标。

* 要列出可用的修饰符和游标处理方法，请使用`db.collection.find().help()`命令：

```
db.collection.find().help()
```

`<collection>`可以是存在的集合的名称，尽管您可以指定不存在的集合。

* 要查看cursor方法的实现，请输入不带括号(())的`db.<collection>.find().<method>`名称，如以下示例所示，它将返回`toArray()`方法的实现：

```
db.collection.find().toArray
```

处理游标的一些有用方法是:

* [`hasNext()`](https://docs.mongodb.com/master/reference/method/cursor.hasNext/#cursor.hasNext)检查光标是否还有更多文档要返回。
* [`next()`](https://docs.mongodb.com/master/reference/method/cursor.next/#cursor.next)返回下一个文档，并将光标位置向前移动一个。
* 迭代整个游标，并将`<function>`应用于光标返回的每个文档。`<function>`期望一个参数，该参数对应于每次迭代的文档。

  有关迭代游标和从游标中检索文档的示例，请参见 [cursor handling](https://docs.mongodb.com/manual/tutorial/iterate-a-cursor/)。有关所有可用的游标方法，另请参见[Cursor](https://docs.mongodb.com/manual/reference/method/#js-query-cursor-methods)。

## **包装对象帮助**

要获取mongo shell中可用的包装器类的列表，例如`BinData()`，请在`mongo shell`中键入`help misc`：

```
help misc
```

另可参考：\
[mongo Shell Methods](https://docs.mongodb.com/manual/reference/method/)

译者：王恒 金江

校对：杨帅


# 为mongo Shell编写脚本

**在本页面**

* [打开新连接](#新连接)
* [交互式mongo与脚本mongo的区别](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/The-Mongo-Shell/区别/README.md)
* [脚本编写](#脚本)

> **\[success] Note**
>
> 下面的文档是[MongoDB服务器下载](https://www.mongodb.com/try/download/community?tck=docs_server).中包含的[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell。有关新的MongoDB Shell ，**mongosh**的信息，请参考[mongosh文档](https://docs.mongodb.com/mongodb-shell/)。
>
> 要了解这两种shell的区别，请参阅[Comparison of the mongo Shell and mongosh](https://docs.mongodb.com/master/mongo/#compare-mongosh-mongo).

您可以为[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell编写JavaScript 的脚本，来处理MongoDB中的数据或执行管理操作。 本章节介绍了通过[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell编写的`JavaScript`的方法 来访问 Mongodb的方式。

## 打开新连接

在[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell或JavaScript文件中，您可以使用[`Mongo()`](https://docs.mongodb.com/master/reference/method/Mongo/#Mongo)构造函数实例化数据库连接：

```
Mongo()
new Mongo(<host>)
new Mongo(<host:port>)
```

请考虑以下示例，该示例实例化与在默认端口上的localhost上运行的MongoDB实例的新连接，并使[`getDB()`](https://docs.mongodb.com/master/reference/method/Mongo.getDB/#Mongo.getDB)方法将全局db变量设置为myDatabase：

```
conn = new Mongo();
db = conn.getDB("myDatabase");
```

如果连接到已经开启了访问控制的MongoDB实例，则可以使用[`db.auth()`](https://docs.mongodb.com/master/reference/method/db.auth/#db.auth) 方法进行身份验证。\
此外，您可以使用`connect()`方法连接到MongoDB实例。 以下示例使用非默认端口**27020**连接到在localhost上运行的MongoDB实例，并设置全局db变量：

```
db = connect("localhost:27020/myDatabase");
```

另可参考：\
[mongo Shell Methods](https://docs.mongodb.com/manual/reference/method/)

## 交互式mongo与脚本mongo的区别

> **\[success] Note**
>
> 从4.2版开始，[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell提供了[`isInteractive()`](https://docs.mongodb.com/master/reference/method/isInteractive/#isInteractive) 方法，该方法返回一个布尔值，该值指示[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell是在交互模式还是脚本模式下运行。

**为mongo shell编写脚本时，请考虑以下事项：**

* 要设置db全局变量，请使用[`getDB()`](https://docs.mongodb.com/master/reference/method/Mongo.getDB/#Mongo.getDB) 方法或`onnect()`方法。您可以将数据库引用分配给**db**以外的其他变量。
* [`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell中的写操作默认情况下使用[{ w: 1 }](https://docs.mongodb.com/master/reference/write-concern/#wc-w)的写入策略。 如果执行批量操作，请使用`Bulk()`方法。 有关更多信息，请参见：[Write Method Acknowledgements](https://docs.mongodb.com/manual/release-notes/2.6-compatibility/#write-methods-incompatibility)）。
* 您不能在JavaScript文件中使用任何shell帮助程序（例如，使用`<dbname>`，**show dbs**等），因为它们不是有效的JavaScript。 下表将最常见的mongo shell助手映射到其JavaScript等效项：

| Shell帮助                  | 等价JavaScript                                                                |
| ------------------------ | --------------------------------------------------------------------------- |
| show dbs, show databases | db.adminCommand('listDatabases')                                            |
| use `<db>`               | db = db.getSiblingDB('`<db>`')                                              |
| show collections         | db.getCollectionNames()                                                     |
| show users               | db.getUsers()                                                               |
| show roles               | db.getRoles({showBuiltinRoles: **true**})                                   |
| show log`<logname>`      | db.adminCommand({ 'getLog' : '`<logname>`' })                               |
| show logs                | db.adminCommand({ 'getLog' : '\*' })                                        |
| it                       | cursor = db.collection.find() **if** ( cursor.hasNext() ){ cursor.next(); } |

在交互模式下， [`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) 打印操作结果，包括所有游标的内容。 在脚本中，使用JavaScript \*\*print()**函数或** [**`mongo`**](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) **特定的**printjson()\*\*函数，该函数返回格式化的JSON。

例子:

要在mongo shell脚本中打印结果游标中的所有项目，请使用以下惯用法：

```java
cursor = db.collection.find();
while ( cursor.hasNext() ) {
    printjson( cursor.next() );
    }
```

## 脚本编写

在系统提示下，使用[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) 评估JavaScript。

**--eval选项**

使用[--eval](/the-mongo-shell/write-scripts-for-the-mongo-shell)选项 让Mongo来执行一个JavaScript片段，如下所示：

```
mongo test --eval "printjson(db.getCollectionNames())"
```

这将使用连接到在本地主机接口上的端口27017上运行的[`mongod`](https://docs.mongodb.com/master/reference/program/mongod/#bin.mongod) 或[`mongos`](https://docs.mongodb.com/master/reference/program/mongos/#bin.mongos)实例的[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell返回[`db.getCollectionNames()`](https://docs.mongodb.com/master/reference/method/db.getCollectionNames/#db.getCollectionNames) 的输出。\
**执行一个JavaScript文件**

您可以在mongo shell中指定.js文件，然后mongo将直接执行JavaScript。 考虑以下示例：

```
mongo localhost:27017/test myjsfile.js
```

此操作在mongo shell中执行`myjsfile.js`脚本，该脚本连接到可通过端口27017上的localhost接口访问的mongod实例上的测试数据库。或者，您可以使用`Mongo()`构造函数在javascript文件中指定mongodb连接参数。\
有关更多信息，请参见：[打开新连接](https://docs.mongodb.com/manual/tutorial/write-scripts-for-the-mongo-shell/#mongo-shell-new-connections) 。\
您可以使用`load()`函数从mongo shell中执行.js文件，如下所示：

```
load("myjstest.js")
```

此函数加载并执行**myjstest.js**文件。\
**load()方法接受相对路径和绝对路径。 如果mongo shell的当前工作目录为/ data / db**，而**myjstest.js**位于\*\*/ data / db / scripts\*\*目录中，则mongo shell中的以下调用将是等效的：

```
load("scripts/myjstest.js")
load("/data/db/scripts/myjstest.js")
```

> **\[success] Note**
>
> **load（）函数没有搜索路径。 如果所需的脚本不在当前工作目录或完整的指定路径中，则**[**`mongo`**](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo)**将无法访问该文件。**

译者：王恒

校对：杨帅


# mongo Shell中的数据类型

**在本页面**

* [类型](#类型)
  * [Date](#date)
  * [ObjectId](#objectid)
  * [NumberLong](#numberlong)
  * [NumberInt](#numberint)
  * [NumberDecimal](#decimal)
* [在mongo Shell中检查类型](#检查)
  * [instanceof](#instanceof)
  * [typeof](#typof)

> **\[success] Note**
>
> 下面的文档是[MongoDB服务器下载](https://www.mongodb.com/try/download/community?tck=docs_server).中包含的[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell。有关新的MongoDB Shell ，**mongosh**的信息，请参考[mongosh文档](https://docs.mongodb.com/mongodb-shell/)。
>
> 要了解这两种shell的区别，请参阅[Comparison of the mongo Shell and mongosh](https://docs.mongodb.com/master/mongo/#compare-mongosh-mongo).

\*\*MongoDB [BSON](https://docs.mongodb.com/master/reference/glossary/#term-bson) 支持除JSON本身支持类型之外的其他数据类型。 驱动程序以宿主语言为这些数据类型提供本机支持，而[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo)shell还提供了一些帮助程序类来支持在[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) JavaScript shell中使用这些数据类型。 有关更多信息，请参阅[Extended JSON](https://docs.mongodb.com/master/reference/mongodb-extended-json/)引用。

## **类型**

### Date

[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell提供了多种返回日期的方法，这些方法可以是字符串，也可以是**Date**对象：

* **Date()** 方法，以字符串形式返回当前日期。
* **new Date()** 构造函数，该构造函数使用`ISODate()`包装器返回Date对象。
* **ISODate()** 构造函数，该构造函数使用`ISODate()`包装器返回Date对象。

  ​

在内部，[Date](https://docs.mongodb.com/master/reference/bson-types/#document-bson-type-date)对象存储为带符号的64位整数，表示自Unix纪元（1970年1月1日）以来的毫秒数。 并非所有的数据库操作和驱动程序都支持完整的64位范围。 您可以安全地处理年份，年份范围在**0**到**9999**之间。\
**以字符串类型返回日期**

以字符串类型返回日期，要用到\*\*Data()\*\*方法，如下所示：

```
var myDateString = Date();
```

要打印变量的值，请在shell中键入变量名称，如下所示：

```
myDateString
```

**myDataString**值的结果如下：

```
Wed Dec 19 2012 01:03:25 GMT-0500 (EST)
```

要验证类型，请使用**typeof**运算符，如下所示：

```
typeof myDateString
```

该操作返回值为 **String**

**Return Date**

[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell使用`ISODate`帮助程序包装Date类型的对象； 但是，对象仍为日期类型。

下面的示例使用新的\*\*Date()**构造函数和**ISODate()\*\*构造函数来返回Date对象。

```
var myDate = new Date();
var myDateInitUsingISODateWrapper = ISODate();
```

您也可以将**new**运算符与\*\*ISODate()\*\*构造函数一起使用。\
要打印变量的值，请在shell中键入变量名称，如下所示：

```
myDate
```

结果是包装在**ISODate()** 帮助器中的**myDate**的**Date**值：

```
ISODate("2012-12-19T06:01:17.171Z")
```

要验证类型，请使用**instanceof**运算符，如下所示：

```
myDate instanceof Date
myDateInitUsingISODateWrapper instanceof Date
```

这两个操作均返回`true`

### **ObjectID**

mongo shell提供了围绕[**ObjectId**](https://docs.mongodb.com/master/reference/bson-types/#objectid) \*\*\*\*数据类型的\*\*ObjectId()\*\*封装类。 要生成新的ObjectId，请在mongo shell中使用以下操作：

```
new ObjectId
```

参考：[ObjectId](https://docs.mongodb.com/manual/reference/method/ObjectId/#ObjectId)

### **NumberLong**

mongo shell默认情况下会将所有数字视为浮点型。mongo shell提供了**NumberLong()** 包装器来处理64位整数。

**NumberLong()** 封装接受long作为字符串：

```
NumberLong("2090845886852")
```

以下示例使用NumberLong（）的封装写入集合：

```
db.collection.insertOne( { _id: 10, calc: NumberLong("2090845886852") } )
db.collection.updateOne( { _id: 10 },         
                    { $set:  { calc: NumberLong("2555555000000") } } )
db.collection.updateOne( { _id: 10 },       
                    { $inc: { calc: NumberLong(5) } } )
```

检索文档以验证：

```
db.collection.findOne( { _id: 10 } )
```

在返回的文档中，calc字段包含一个NumberLong对象：

```
{ "_id" : 10, "calc" : NumberLong("2555555000005") }
```

如果使用[`$inc`](https://docs.mongodb.com/master/reference/operator/update/inc/#up._S_inc)通过浮点数递增包含**NumberLong**对象的字段的值，则数据类型将更改为浮点值，如以下示例所示：

1.使用[`$inc`](https://docs.mongodb.com/master/reference/operator/update/inc/#up._S_inc) 将**calc**字段增加 **5**，[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell将其视为浮点数：

```
db.collection.updateOne( { _id: 10 },
                            { $inc: { calc: 5 } } )
```

2.检索更新的文档：

```
db.collection.findOne( { _id: 10 } )
```

在更新的文档中，calc字段包含一个浮点值：

```
{ "_id" : 10, "calc" : 2555555000010 }
```

### **NumberInt**

mongo shell默认情况下会将所有数字视为浮点值。 mongo shell提供\*\*NumberInt()\*\*构造函数来显式指定32位整数。

### **NumberDecimal**

**始于3.4版本**\
mongo shell默认将所有数字视为64位浮点双精度值。 mongo shell提供了\*\*NumberDecimal()\*\*构造函数来显式指定基于128位的基于十进制的浮点值，该值能够精确地模拟十进制舍入。 此功能适用于处理货币数据的应用程序，例如金融、税收和科学计算。\
十进制BSON类型使用IEEE 754十进制128浮点编号格式，该格式支持34个十进制数字（即有效数字）和-6143至+6144的指数范围。\
NumberDecimal（）构造函数接受十进制值作为字符串：

```
NumberDecimal("1000.55")
```

该值存储在数据库中，如下所示：

```
NumberDecimal("1000.55")
```

\*\*NumberDecimal()\*\*构造函数还接受mongo shell中的双精度值（即不带引号），尽管不建议这样做，因为这样做可能会丢失精度。 构造函数创建基于二进制的双精度表示形式的基于十进制的参数（可能会丢失精度），然后将该值转换为精度为15位数字的十进制值。 下面的示例隐式地将值作为双精度值传递，并显示如何以15位精度创建值：

```
NumberDecimal(1000.55)
```

该值存储在数据库中，如下所示：

```
NumberDecimal("1000.55000000000")
```

下面的示例隐式地将该值作为双精度值传递，并说明如何发生精度损失：

```
NumberDecimal(9999999.4999999999)
```

该值存储在数据库中，如下所示：

```
NumberDecimal("9999999.50000000")
```

> **\[success] Note**
>
> **要将十进制数据类型与MongoDB驱动程序一起使用，请确保使用支持该格式的驱动程序版本。**

### 相等和排序顺序

比较十进制类型的值，并根据其实际数字值与其他数字类型进行排序。 基于二进制的double类型的数值通常具有基于十进制值的近似表示，并且可能不完全等于其十进制表示，因此在检查十进制值的相等性时，请使用\*\*NumberDecimal()\*\*构造函数。 考虑以下示例以及带有数字集合中的以下文档：

```
{ "_id" : 1, "val" : NumberDecimal( "9.99" ), "description" : "Decimal" }
{ "_id" : 2, "val" : 9.99, "description" : "Double" }
{ "_id" : 3, "val" : 10, "description" : "Double" }
{ "_id" : 4, "val" : NumberLong(10), "description" : "Long" }
{ "_id" : 5, "val" : NumberDecimal( "10.0" ), "description" : "Decimal" }
```

将下表中的查询插入`db.numbers.find（<query>）`方法时，将返回以下结果：

| 查询                                     | 结果                                                                                                                                                                                                |
| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **{ “val”: 9.99 }**                    | **{ “\_id”: 2, “val”: 9.99, “description”: “Double” }**                                                                                                                                           |
| **{ “val”: NumberDecimal( “9.99” ) }** | **{ “\_id”: 1, “val”: NumberDecimal( “9.99” ), “description”: “Decimal” }**                                                                                                                       |
| **{ val: 10 }**                        | **{ “\_id”: 3, “val”: 10, “description”: “Double” }** **{ “\_id”: 4, “val”: NumberLong(10), “description”: “Long” }** **{ “\_id”: 5, “val”: NumberDecimal( “10.0” ), “description”: “Decimal” }** |
| **{ val: NumberDecimal( “10” ) }**     | **{ “\_id”: 3, “val”: 10, “description”: “Double” }** **{ “\_id”: 4, “val”: NumberLong(10), “description”: “Long” }** **{ “\_id”: 5, “val”: NumberDecimal( “10.0” ), “description”: “Decimal” }** |

第一个查询 **{“ val”：9.99}** 隐式搜索**9.99**的双精度表示形式，该表示形式不等于该值的十进制表示形式。\
**NumberDecimal()** 构造函数用于查询以**9.99**十进制表示的文档。 排除双精度类型的值，因为它们与**9.99**的十进制表示形式的确切值不匹配。 查询整数时，将返回所有数字类型的匹配值。 例如，查询10的双精度表示将在结果中包含**10.0**的十进制表示，反之亦然。 **检查十进制类型**

要测试十进制类型，请使用[`$type`](https://docs.mongodb.com/master/reference/operator/query/type/#op._S_type)运算符，其字符串别名为\*\*“decimal”**或**19\*\*（十进制类型的数字代码）。

```
db.inventory.find( { price: { $type: "decimal" } } )
```

## **在mongo Shell中检查类型**

为了确定字段的类型，mongo shell提供了**instanceof**和**typeof**运算符。

### **instanceof**

**instanceof**返回一个布尔值，以测试值是否是某种类型的实例。\
例如，以下操作测试\*\*\_id**字段是否为**ObjectId\*\*类型的实例：

```
mydoc._id instanceof ObjectId
```

该操作返回**true**。

### **typeof**

typeof返回字段的类型。

例如，以下操作返回\*\*\_id\*\*字段的类型：

```
typeof mydoc._id
```

在这种情况下，typeof将返回更通用的**object** 类型，而不是**ObjectId**类型。

译者：王恒

校对：杨帅


# mongo Shell 快速参考

**在本页面**

* [mongo Shell命令历史](#命令历史)
* [命令行选项](#命令行选项)
* [命令助手](#助手)
* [Shell基本JavaScript操作](#shell)
* [键盘快捷键](#快捷键)
* [查询](#查询)
* [错误检查方法](#错误检查)
* [行政命令助手](#行政命令助手)
* [打开其他连接](#其他连接)
* [多样式](#多样式)
* [其他资源](#其他资源)

> **\[success] Note**
>
> 下面的文档是[MongoDB服务器下载](https://www.mongodb.com/try/download/community?tck=docs_server).中包含的[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell。有关新的MongoDB Shell ，**mongosh**的信息，请参考[mongosh文档](https://docs.mongodb.com/mongodb-shell/)。
>
> 要了解这两种shell的区别，请参阅[Comparison of the mongo Shell and mongosh](https://docs.mongodb.com/master/mongo/#compare-mongosh-mongo).

## mongo Shell命令历史

您可以使用上下箭头键检索在 [`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell中发布的先前命令。 命令历史记录存储在\*\*〜/ .dbshell\*\*文件中。 有关更多信息，请参见[.dbshell](https://docs.mongodb.com/master/reference/program/mongo/#mongo-dbshell-file) 。

### 命令行选项

[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell可以使用许多选项启动。 有关所有可用选项的详细信息，请参见[mongo shell](https://docs.mongodb.com/master/reference/program/mongo/) 页面。

下表显示了mongo的一些常用选项：

| 选项                                                      | 说明                                                                                                                                                                                                                                                    |
| ------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [--help](/the-mongo-shell/mongo-shell-quick-reference)  | 显示命令行选项                                                                                                                                                                                                                                               |
| [--nodb](/the-mongo-shell/mongo-shell-quick-reference)  | 在不连接数据库的情况下启动mongo shell。 要稍后连接，请参阅[Opening New Connections](https://docs.mongodb.com/manual/tutorial/write-scripts-for-the-mongo-shell/#mongo-shell-new-connections)。                                                                                |
| [--shell](/the-mongo-shell/mongo-shell-quick-reference) | 与JavaScript文件（即<[file.js](/the-mongo-shell/mongo-shell-quick-reference)>]）结合使用，以在运行JavaScript文件后在mongo shell中继续。 有关示例，请参见 [JavaScript file](https://docs.mongodb.com/manual/tutorial/write-scripts-for-the-mongo-shell/#mongo-shell-javascript-file)。 |

## **命令助手**

[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo)shell提供了各种帮助。下表显示了一些常见的帮助方法和命令：

| 帮助方法和命令                                                                          | 描述                                                                                                                                                                                                                                                                               |
| -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| help()                                                                           | 打印当前数据库的列表                                                                                                                                                                                                                                                                       |
| [`db.help()`](https://docs.mongodb.com/master/reference/method/db.help/#db.help) | 打印当前数据库的所有角色的列表，包括用户定义的角色和内置角色。                                                                                                                                                                                                                                                  |
| db.`<collection>`.help()                                                         | 打印耗时1毫秒或更长时间的五个最新操作。 有关更多信息，请参见数据库分析器上的文档。                                                                                                                                                                                                                                       |
| show dbs                                                                         | 打印所有可用数据库的列表。 该操作对应于[`listDatabases`](https://docs.mongodb.com/master/reference/command/listDatabases/#dbcmd.listDatabases)命令。 如果部署使用访问控制运行，则该操作将根据用户权限返回不同的值。 有关详细信息，请参见 [listDatabases](https://docs.mongodb.com/manual/reference/command/listDatabases/#dbcmd.listDatabases)。 |
| use<`db`>                                                                        | 将当前数据库切换到<`db`>。 [`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell变量**db**设置为当前数据库。                                                                                                                                                            |
| show collections                                                                 | 打印当前数据库的所有集合的列表。 另可参考： [show collections](https://docs.mongodb.com/manual/release-notes/4.0-compatibility/#compat-show-collections)                                                                                                                                              |
| show users                                                                       | 打印当前数据库列表                                                                                                                                                                                                                                                                        |
| show roles                                                                       | 打印当前数据库的所有角色的列表，包括用户定义角色和内置角色。                                                                                                                                                                                                                                                   |
| show profile                                                                     | 打印耗时1毫秒或更长时间的五个最新操作。 有关更多信息，请参见 [database profiler](https://docs.mongodb.com/manual/tutorial/manage-the-database-profiler/)。                                                                                                                                                     |
| show databases                                                                   | 打印所有可用数据库的列表。 该操作对应于 [listDatabases](https://docs.mongodb.com/manual/reference/command/listDatabases/#dbcmd.listDatabases) 命令。 如果部署使用访问控制运行，则该操作将根据用户权限返回不同的值。 有关详细信息，请参见 [listDatabases](https://docs.mongodb.com/manual/reference/command/listDatabases/#dbcmd.listDatabases)。 |
| load()                                                                           | 执行一个JavaScript文件。 有关更多信息，请参见 [Write Scripts for the mongo Shell](https://docs.mongodb.com/manual/tutorial/write-scripts-for-the-mongo-shell/)。                                                                                                                                   |

## **Shell基本JavaScript操作**

[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell提供了用于数据库操作的[JavaScript API](https://docs.mongodb.com/master/reference/method/) 。

在mongo shell中，**db**是引用当前数据库的变量。该变量自动设置为默认数据库测试，或者在\*\*use <`db`>\*\*切换当前数据库时设置。

下表显示了一些常见的JavaScript操作：

| JavaScript数据库操作                                                                                                                      | 说明                                                                                                      |
| ------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------- |
| [db.auth()](https://docs.mongodb.com/manual/reference/method/db.auth/#db.auth)                                                       | 如果以安全模式运行，请对用户进行身份验证。                                                                                   |
| coll = db.<`collection`>                                                                                                             | 将当前数据库中的特定集合设置为变量coll，如以下示例所示： coll = db.myCollection; 您可以使用变量在myCollection上执行操作，如以下示例所示： coll.find();  |
| [db.collection.find()](https://docs.mongodb.com/manual/reference/method/db.collection.find/#db.collection.find)                      | 查找集合中的所有文档并返回一个游标。 有关更多信息和示例，请参见db.collection.find（）和查询文档。 有关在mongo shell中处理游标的信息，请参阅在mongo Shell中迭代游标。 |
| [db.collection.insertOne()](https://docs.mongodb.com/manual/reference/method/db.collection.insertOne/#db.collection.insertOne)       | 将新文档插入集合中。                                                                                              |
| [db.collection.insertMany()](https://docs.mongodb.com/manual/reference/method/db.collection.insertMany/#db.collection.insertMany)    | 将多个新文档插入集合中。                                                                                            |
| [db.collection.updateOne()](https://docs.mongodb.com/manual/reference/method/db.collection.updateOne/#db.collection.updateOne)       | 更新集合中的单个现有文档。                                                                                           |
| [db.collection.updateMany()](https://docs.mongodb.com/manual/reference/method/db.collection.updateMany/#db.collection.updateMany)    | 更新集合中的多个现有文档。                                                                                           |
| [db.collection.save()](https://docs.mongodb.com/manual/reference/method/db.collection.save/#db.collection.save)                      | 插入新文档或更新集合中的现有文档。                                                                                       |
| [db.collection.deleteOne()](https://docs.mongodb.com/manual/reference/method/db.collection.deleteOne/#db.collection.deleteOne)       | 从集合中删除单个文档。                                                                                             |
| [db.collection.deleteMany()](https://docs.mongodb.com/manual/reference/method/db.collection.deleteMany/#db.collection.deleteMany)    | 从集合中删除多个文档                                                                                              |
| [db.collection.drop()](https://docs.mongodb.com/manual/reference/method/db.collection.drop/#db.collection.drop)                      | 完全删除或除去集合。                                                                                              |
| [db.collection.createIndex()](https://docs.mongodb.com/manual/reference/method/db.collection.createIndex/#db.collection.createIndex) | 如果索引不存在，则在集合上创建一个新索引；否则，该操作无效。                                                                          |
| [db.getSiblingDB()](https://docs.mongodb.com/manual/reference/method/db.getSiblingDB/#db.getSiblingDB)                               | 使用相同的连接返回对另一个数据库的引用，而无需显式切换当前数据库。 这允许跨数据库查询。                                                            |

有关在shell中执行操作的更多信息，请参见：

* [MongoDB CRUD Operations](https://docs.mongodb.com/manual/crud/)
* [mongo Shell Methods](https://docs.mongodb.com/manual/reference/method/#js-administrative-methods)

## **键盘快捷键**

shell提供了大多数键盘快捷键，类似于**bash shell**或**Emacs**中的快捷键。 对于某些功能，[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) 提供了多个键绑定，以适应几种熟悉的范例。

下表列举了 [`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell支持的按键：

| 按键                      | 功能                |
| ----------------------- | ----------------- |
| Up-arrow                | 以前的历史             |
| Down-arrow              | 下一个历史             |
| Home                    | 行起点               |
| End                     | 行尾                |
| Tab                     | 自动完成              |
| Left-arrow              | 后退字符              |
| Right-arrow             | 向前字符              |
| Ctrl-left-arrow         | 后向词               |
| Ctrl-right-arrow        | 前向词               |
| Meta-left-arrow         | 后向词               |
| Meta-right-arrow        | 前向词               |
| Ctrl-A                  | 上线                |
| Ctrl-B                  | 向后字符              |
| Ctrl-C                  | 退出                |
| Ctrl-D                  | 删除字符（或退出）         |
| Ctrl-E                  | 行结束               |
| Ctrl-F                  | 转发字符              |
| Ctrl-G                  | 中止                |
| Ctrl-J                  | 接受线               |
| Ctrl-K                  | 杀死线               |
| Ctrl-L                  | 清除屏幕              |
| Ctrl-M                  | 接受线               |
| Ctrl-N                  | 下一个历史记录           |
| Ctrl-P                  | 以前的历史记录           |
| Ctrl-R                  | 反向搜索历史            |
| Ctrl-S                  | 正向搜索历史            |
| Ctrl-T                  | 转置字符              |
| Ctrl-U                  | 丢弃Unix线           |
| Ctrl-W                  | Unix单词清除          |
| Ctrl-Y                  | 拉动                |
| Ctrl-Z                  | 挂起（作业控制在Linux中有效） |
| Ctrl-H (i.e. Backspace) | 向后删除字符            |
| Ctrl-I (i.e. Tab)       | 完成                |
| Meta-B                  | 后退词               |
| Meta-C                  | 大写词               |
| Meta-D                  | 杀死命令              |
| Meta-F                  | 转发字               |
| Meta-L                  | 小写词               |
| Meta-U                  | 大写词               |
| Meta-Y                  | yank-pop          |
| Meta-\[Backspace]       | 撤销杀死命令            |
| Meta-<                  | 历史开始              |
| Meta->                  | 历史结束              |

## **查询**

在mongo shell中，使用[`find()`](https://docs.mongodb.com/master/reference/method/db.collection.find/#db.collection.find) 和[`findOne()`](https://docs.mongodb.com/master/reference/method/db.collection.findOne/#db.collection.findOne) 方法执行读取操作。\
[`find()`](https://docs.mongodb.com/master/reference/method/db.collection.find/#db.collection.find)方法返回一个游标对象，[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell对其进行迭代以在屏幕上打印文档。 默认情况下，[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) 打印前20个结果。[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell将提示用户“输入”以继续迭代接下来的20个结果。\
下表提供了mongo shell中的一些常见读取操作：

| 读取操作                                                                                                                                     | 说明描述                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| ---------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`db.collection.find(<query>`)](https://docs.mongodb.com/manual/reference/method/db.collection.find/#db.collection.find)                 | 在集合中找到符合<`query`>条件的文档。 如果未指定<`query`>条件或该条件为空（即{}），则读取操作将选择集合中的所有文档。 以下示例在用户集合中选择name字段等于“ Joe”的文档：coll = db.users;coll.find( { name: "Joe" } );有关指定<`query`>条件的更多信息，请参见： [Specify Equality Condition](https://docs.mongodb.com/manual/tutorial/query-documents/#read-operations-query-argument).                                                                                                                                      |
| [`db.collection.find(<query>,` `<projection>)`](https://docs.mongodb.com/manual/reference/method/db.collection.find/#db.collection.find) | 查找符合<`query`>条件的文档，并仅返回<`projection`>中的特定字段。 以下示例从集合中选择所有文档，但仅返回名称字段和\*\*\_id**字段。 除非明确指定不返回，否则始终返回**\_id\*\*。 **coll = db.users;** **coll.find（{}，{name：true}）;** 有关指定<`projection`>的更多信息，请参见[Project Fields to Return from Query](https://docs.mongodb.com/master/tutorial/project-fields-from-query-results/#read-operations-projection).。                                                                                           |
| [`db.collection.find().sort(<sort order>)`](https://docs.mongodb.com/manual/reference/method/cursor.sort/#cursor.sort)                   | 以指定的<`sort order`>返回结果。 以下示例从集合中选择所有文档，并返回按名称字段升序+1排序的结果。 使用-1降序： **coll = db.users;** **coll.find（）。sort（{name：1}）;**                                                                                                                                                                                                                                                                                                                  |
| [`db.collection.find(<query>).sort(<sort` `order`>)](https://docs.mongodb.com/manual/reference/method/cursor.sort/#cursor.sort)          | 以指定的<`sort order`>返回符合<`query`>条件的文档。                                                                                                                                                                                                                                                                                                                                                                                                   |
| [`db.collection.find( ... ).limit( )`](https://docs.mongodb.com/master/reference/method/cursor.limit/#cursor.limit)                      | 将结果限制为<`n`>行。 如果只需要一定数量的行以获得最佳性能，则强烈建议使用。                                                                                                                                                                                                                                                                                                                                                                                               |
| [`db.collection.find( ... ).skip( )`](https://docs.mongodb.com/master/reference/method/cursor.skip/#cursor.skip)                         | 跳过<`n`>个结果。                                                                                                                                                                                                                                                                                                                                                                                                                             |
| [db.collection.count()](https://docs.mongodb.com/manual/reference/method/db.collection.count/#db.collection.count)                       | 返回集合中的文档总数。                                                                                                                                                                                                                                                                                                                                                                                                                             |
| [`db.collection.find().count()`](https://docs.mongodb.com/master/reference/method/cursor.count/#cursor.count)                            | 返回与查询匹配的文档总数。 [`count()`](https://docs.mongodb.com/master/reference/method/cursor.count/#cursor.count)忽略[`limit()`](https://docs.mongodb.com/master/reference/method/cursor.limit/#cursor.limit)和[`skip()`](https://docs.mongodb.com/master/reference/method/cursor.skip/#cursor.skip).例如，如果有100条记录匹配，但限制为10，则[`count()`](https://docs.mongodb.com/master/reference/method/cursor.count/#cursor.count)将返回100。这比迭代自己的速度更快，但仍然需要时间。       |
| [`db.collection.findOne()`](https://docs.mongodb.com/master/reference/method/db.collection.findOne/#db.collection.findOne)               | 查找并返回一个文档。 如果找不到，则返回null。 以下示例在用户集合中选择一个名称与“ Joe”匹配的文档： **coll = db.users;** **coll.findOne（{name：“ Joe”}）;** 在内部，[**`findOne()`**](https://docs.mongodb.com/master/reference/method/db.collection.findOne/#db.collection.findOne)方法是带有[`limit(1)`](https://docs.mongodb.com/master/reference/method/cursor.limit/#cursor.limit)的[`find()`](https://docs.mongodb.com/master/reference/method/db.collection.find/#db.collection.find)方法。 |

有关更多信息和示例，请参阅[Query Documents](https://docs.mongodb.com/manual/tutorial/query-documents/) 。 请参阅[Query and Projection Operators](https://docs.mongodb.com/manual/reference/operator/query/)。

## **错误检查方法**

mongo shell write方法将**Write Concern**直接集成到方法执行中，并返回一个\*\*WriteResult()\*\*对象，该对象包含操作结果，包括所有写错误和写关注错误。

**行政命令助手**

下表列出了一些支持数据库管理的常用方法：

| JavaScript数据库管理                                                                                                                                             | 方法说明                                                                                                                                  |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| [`db.fromColl.renameCollection(<toColl>)`](https://docs.mongodb.com/manual/reference/method/db.collection.renameCollection/#db.collection.renameCollection) | 将集合从**fromColl**重命名为<`toColl`>。 请参阅[Naming Restrictions](https://docs.mongodb.com/manual/reference/limits/#restrictions-on-db-names)。 |
| [`db.getCollectionNames()`](https://docs.mongodb.com/manual/reference/method/db.getCollectionNames/#db.getCollectionNames)                                  | 获取当前数据库中所有集合的列表。                                                                                                                      |
| [`db.dropDatabase()`](https://docs.mongodb.com/manual/reference/method/db.dropDatabase/#db.dropDatabase)                                                    | 删除当前数据库。                                                                                                                              |

另请参见[administrative database methods](https://docs.mongodb.com/manual/reference/method/#js-administrative-methods)以获取方法的完整列表。

## **打开其他连接**

您可以在mongo shell中创建新的连接。\
下表显示了创建连接的方法：

| JavaScript连接创建方法                                 | 说明                                          |
| ------------------------------------------------ | ------------------------------------------- |
| db = connect("<`host`><:port>/<`dbname`>")       | 打开一个新的数据库连接。                                |
| conn = **new** Mongo() db = conn.getDB("dbname") | 使用新的Mongo（）打开与新服务器的连接。 使用连接的getDB（）方法选择数据库。 |

另请参阅 [Opening New Connections](https://docs.mongodb.com/manual/tutorial/write-scripts-for-the-mongo-shell/#mongo-shell-new-connections)以获取有关从mongo shell打开新连接的更多信息。

## **多样式**

下表显示了一些其他方法：

| 方法                            | 描述                                                                                                               |
| ----------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| Object.bsonsize(<`document`>) | Prints the [BSON](https://docs.mongodb.com/manual/reference/glossary/#term-bson) size of a <`document`> in bytes |

## **其他资源**

考虑以下解决mongo shell及其接口的参考资料：

* [mongo](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo)
* [mongo Shell Methods](https://docs.mongodb.com/manual/reference/method/#js-administrative-methods)
* [Database Commands](https://docs.mongodb.com/manual/reference/command/#database-commands)
* [Aggregation Reference](https://docs.mongodb.com/manual/reference/aggregation/#aggregation-reference)
* [Getting Started Guide](https://docs.mongodb.com/getting-started/shell)

另外，MongoDB源代码存储库包括一个[jstests](https://github.com/mongodb/mongo/tree/master/jstests/)目录，该目录包含许多mongo shell脚本。

译者：王恒

校对：杨帅


# MongoDB CRUD操作

**在本页面**

* [创建操作](#创建)
* [读取操作](#读取)
* [更新操作](#更新)
* [删除操作](#删除)
* [批量写入](#批量)

  **CURD操作指的是文档的*****创建*****、*****读*****、*****更新*****以及*****删除*****操作。**

## 创建操作

创建或插入操作会将新[文档](https://docs.mongodb.com/master/core/document/#bson-document-format)添加到[集合](https://docs.mongodb.com/master/core/databases-and-collections/#collections)中。 如果该集合当前不存在，则插入操作将创建该集合。

MongoDB提供以下将文档插入集合的方法：

* [`db.collection.insertOne()`](https://docs.mongodb.com/manual/reference/method/db.collection.insertOne/#db.collection.insertOne) *3.2版中的新功能*
* [`db.collection.insertMany()`](https://docs.mongodb.com/manual/reference/method/db.collection.insertMany/#db.collection.insertMany) *3.2版中的新功能*

在MongoDB中，插入操作针对单个[集合](https://docs.mongodb.com/master/core/databases-and-collections/#collections)。 MongoDB中的所有写操作都是单个文档级别的[原子](https://docs.mongodb.com/master/core/write-operations-atomicity/)操作。![](https://docs.mongodb.com/master/_images/crud-annotated-mongodb-insertOne.bakedsvg.svg)

有关示例，请参见[插入文档](https://docs.mongodb.com/manual/tutorial/insert-documents/)。

## 读取操作

读取操作从集合中检索文档； 即查询集合中的文档。 MongoDB提供了以下方法来从集合中读取文档：

* [db.collection.find()](https://docs.mongodb.com/manual/reference/method/db.collection.find/#db.collection.find)

您可以指定查询过滤器或条件以标识要返回的文档。

![](https://docs.mongodb.com/master/_images/crud-annotated-mongodb-find.bakedsvg.svg)

**有关示例，请参见：**

* [查询文件](https://docs.mongodb.com/manual/tutorial/query-documents/)
* [查询嵌入/嵌套文档](https://docs.mongodb.com/manual/tutorial/query-embedded-documents/)
* [查询数组](https://docs.mongodb.com/manual/tutorial/query-arrays/)
* [查询嵌入式文档数组](https://docs.mongodb.com/manual/tutorial/query-array-of-documents/)

## 更新操作

更新操作会修改集合中的现有文档。 MongoDB提供了以下更新集合文档的方法：

* [`db.collection.updateOne()`](https://docs.mongodb.com/manual/reference/method/db.collection.updateOne/#db.collection.updateOne) *3.2版中的新功能*
* [`db.collection.updateMany()`](https://docs.mongodb.com/manual/reference/method/db.collection.updateMany/#db.collection.updateMany) *3.2版中的新功能*
* [`db.collection.replaceOne()`](https://docs.mongodb.com/manual/reference/method/db.collection.replaceOne/#db.collection.replaceOne) *3.2版中的新功能*

在MongoDB中，更新操作针对单个集合。 MongoDB中的所有写操作都是单个文档级别的原子操作。

您可以指定标准或过滤器，以标识要更新的文档。 这些过滤器使用与读取操作相同的语法。![](https://docs.mongodb.com/master/_images/crud-annotated-mongodb-updateMany.bakedsvg.svg)

有关示例，请参见[更新文档](https://docs.mongodb.com/manual/tutorial/update-documents/)。

## 删除操作

删除操作从集合中删除文档。 MongoDB提供以下删除集合文档的方法：

* [`db.collection.deleteOne()`](https://docs.mongodb.com/manual/reference/method/db.collection.deleteOne/#db.collection.deleteOne) *3.2版中的新功能*
* [`db.collection.deleteMany()`](https://docs.mongodb.com/manual/reference/method/db.collection.deleteMany/#db.collection.deleteMany) *3.2版中的新功能*

在MongoDB中，删除操作只针对单个集合。MongoDB中的所有写操作都是单个文档级别的原子 操作。

你可以指定查询过滤器或条件来标识要更新的文档，这里的过滤器和读操作的语法是一致的。

![](https://docs.mongodb.com/master/_images/crud-annotated-mongodb-deleteMany.bakedsvg.svg)

有关示例，请参见[删除文档](https://docs.mongodb.com/manual/tutorial/remove-documents/)。

## 批量写入

MongoDB提供了批量执行写入操作的功能。有关详细信息，请参见[批量写入操作](https://docs.mongodb.com/manual/core/bulk-write-operations/)。

译者：刘翔 杨帅

### MongoDB中文社区

![MongoDB中文社区—MongoDB爱好者技术交流平台](https://mongoing.com/wp-content/uploads/2020/09/6de8a4680ef684d-2.png)

| 资源列表推荐             | 资源入口                                                                                                                                                                                                                                                                       |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| MongoDB中文社区官网      | <https://mongoing.com/>                                                                                                                                                                                                                                                    |
| 微信服务号 ——最新资讯和优质文章  | Mongoing中文社区（mongoing-mongoing）                                                                                                                                                                                                                                            |
| 微信订阅号 ——发布文档翻译内容   | MongoDB中文用户组（mongoing123）                                                                                                                                                                                                                                                  |
| 官方微信号 —— 官方最新资讯    | MongoDB数据库（MongoDB-China）                                                                                                                                                                                                                                                  |
| MongoDB中文社区组委会成员介绍 | <https://mongoing.com/core-team-members>                                                                                                                                                                                                                                   |
| MongoDB中文社区翻译小组介绍  | <https://mongoing.com/translators>                                                                                                                                                                                                                                         |
| MongoDB中文社区微信技术交流群 | 添加社区助理小芒果微信（ID:mongoingcom），并备注 mongo                                                                                                                                                                                                                                      |
| MongoDB中文社区会议及文档资源 | <https://mongoing.com/resources>                                                                                                                                                                                                                                           |
| MongoDB中文社区大咖博客    | [基础知识](https://mongoing.com/basic-knowledge) [性能优化](https://mongoing.com/performance-optimization) [原理解读](https://mongoing.com/interpretation-of-principles) [运维监控](https://mongoing.com/operation-and-maintenance-monitoring) [最佳实践](https://mongoing.com/best-practices) |
| MongoDB白皮书         | <https://mongoing.com/mongodb-download-white-paper>                                                                                                                                                                                                                        |
| MongoDB初学者教程-7天入门  | <https://mongoing.com/mongodb-beginner-tutorial>                                                                                                                                                                                                                           |
| 社区活动邮件订阅           | <https://sourl.cn/spszjN>                                                                                                                                                                                                                                                  |


# 插入文档

该页面提供了MongoDB中插入操作的示例。

> **建立集合**
>
> 如果该集合当前不存在，则插入操作将创建该集合。

## **插入一个文件**

[`db.collection.insertOne()`](https://docs.mongodb.com/manual/reference/method/db.collection.insertOne/#db.collection.insertOne)将单个[文档](https://docs.mongodb.com/master/core/document/#bson-document-format)插入集合中。

以下示例将一个新文档插入库存集合。 如果文档未指定\*\*\_id**字段，则MongoDB将具有**ObjectId**值的**\_id\*\*字段添加到新文档中。 请参阅[插入行为](https://docs.mongodb.com/manual/tutorial/insert-documents/#write-op-insert-behavior)。

```
db.inventory.insertOne(  
        { item: "canvas", qty: 100, tags: ["cotton"], size: { h: 28, w: 35.5, uom: "cm" } }
)
```

[`insertOne()`](https://docs.mongodb.com/master/reference/method/db.collection.insertOne/#db.collection.insertOne)返回一个文档，其中包含新插入的文档的\_id字段值。有关返回文档的示例，请参阅[`db.collection.insertOne() reference`](https://docs.mongodb.com/master/reference/method/db.collection.insertOne/#insertone-examples)引用。

要检索刚刚插入的文档，[查询集合:](https://docs.mongodb.com/master/core/document/#document-query-filter)

```
db.inventory.find( { item: "canvas" } )
```

## **插入多个文件**

*3.2版中的新功能*

[db.collection.insertMany()](https://docs.mongodb.com/manual/reference/method/db.collection.insertMany/#db.collection.insertMany)可以将多个文档插入一个集合中。 将文档数组传递给该方法。

下面的示例将三个新文档插入库存集合。 如果文档未指定\*\*\_id**字段，则MongoDB向每个文档添加带有**ObjectId**值的**\_id\*\*字段。 请参阅 [插入行为](https://docs.mongodb.com/manual/tutorial/insert-documents/#write-op-insert-behavior)。

```
db.inventory.insertMany([
        { item: "journal", qty: 25, tags: ["blank", "red"], size: { h: 14, w: 21, uom: "cm" } }, 
        { item: "mat", qty: 85, tags: ["gray"], size: { h: 27.9, w: 35.5, uom: "cm" } },
        { item: "mousepad", qty: 25, tags: ["gel", "blue"], size: { h: 19, w: 22.85, uom: "cm" } }
    ])
```

返回包含新插入的文档\*\*\_id\*\*字段值的文档。 有关示例，请参见[参考](https://docs.mongodb.com/manual/reference/method/db.collection.insertMany/#insertmany-examples)。

要检索插入的文档，[查询集合:](https://docs.mongodb.com/master/core/document/#document-query-filter)

```
db.inventory.find( {} )
```

## **插入行为**

### 集合创建

如果该集合当前不存在，则插入操作将创建该集合。

### `_id` Field

在MongoDB中，存储在集合中的每个文档都需要一个唯一的\*\*\_id**字段作为主键。 如果插入的文档省略**\_id**字段，则MongoDB驱动程序会自动为**\_id**字段生成**ObjectId\*\*。

这也适用于通过[upsert：true](/mongodb-crud-operations/insert-documents)通过更新操作插入的文档。

### 原子性

MongoDB中的所有写操作都是单个文档级别的原子操作。 有关MongoDB和原子性的更多信息，请参见[原子性和事务](https://docs.mongodb.com/manual/core/write-operations-atomicity/).

### 写确认书

对于写入问题，您可以指定从MongoDB请求的写入操作的确认级别。 有关详细信息，请参见[写关注](https://docs.mongodb.com/manual/reference/write-concern/)。

另可参考：

* [db.collection.insertOne()](https://docs.mongodb.com/manual/reference/method/db.collection.insertOne/#db.collection.insertOne)
* [db.collection.insertMany()](https://docs.mongodb.com/manual/reference/method/db.collection.insertMany/#db.collection.insertMany)
* [Additional Methods for Inserts](https://docs.mongodb.com/manual/reference/insert-methods/#additional-inserts)

译者：杨帅

校对：杨帅


# 插入方法

**MongoDB 提供了以下方法将文件插入集合**：

|                                                                                                                                   |                                                                                                                                              |
| --------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| [db.collection.insertOne()](https://docs.mongodb.com/manual/reference/method/db.collection.insertOne/#db.collection.insertOne)    | 将单个文档插入到集合中。                                                                                                                                 |
| [db.collection.insertMany()](https://docs.mongodb.com/manual/reference/method/db.collection.insertMany/#db.collection.insertMany) | [db.collection.insertMany()](https://docs.mongodb.com/manual/reference/method/db.collection.insertMany/#db.collection.insertMany)将多个文件插入集合中。 |
| [db.collection.insert()](https://docs.mongodb.com/manual/reference/method/db.collection.insert/#db.collection.insert)             | [db.collection.insert()](https://docs.mongodb.com/manual/reference/method/db.collection.insert/#db.collection.insert)将单个文档或多个文档插入到集合中。       |

## 插入的其他方法

以下方法还可以向集合中添加新文档：

* 与`upsert: true`选项一起使用时[db.collection.update()](https://docs.mongodb.com/manual/reference/method/db.collection.update/#db.collection.update)。
* 与`upsert: true`选项一起使用时[db.collection.updateOne()](https://docs.mongodb.com/manual/reference/method/db.collection.updateOne/#db.collection.updateOne)。
* 与`upsert: true`选项一起使用时[db.collection.updateMany()](https://docs.mongodb.com/manual/reference/method/db.collection.updateMany/#db.collection.updateMany)。
* 与`upsert: true`选项一起使用时[db.collection.findAndModify()](https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/#db.collection.findAndModify)。
* 与`upsert: true`选项一起使用时[db.collection.findOneAndUpdate()](https://docs.mongodb.com/manual/reference/method/db.collection.findOneAndUpdate/#db.collection.findOneAndUpdate)。
* 与`upsert: true`选项一起使用时[db.collection.findOneAndReplace()](https://docs.mongodb.com/manual/reference/method/db.collection.findOneAndReplace/#db.collection.findOneAndReplace)。
* [db.collection.save()](https://docs.mongodb.com/manual/reference/method/db.collection.save/#db.collection.save).
* [db.collection.bulkWrite()](https://docs.mongodb.com/manual/reference/method/db.collection.bulkWrite/#db.collection.bulkWrite).

有关更多信息和示例，请参阅方法的各个 reference 页面。

译者：杨帅

校对：杨帅


# 查询文档

本文提供了使用mongo shell中[db.collection.find()](https://docs.mongodb.com/v4.0/reference/method/db.collection.find/#db.collection.find)方法查询的案例。案例中使用的**inventory**集合数据可以通过下面的语句产生。

```javascript
db.inventory.insertMany([
   { item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
   { item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in" }, status: "A" },
   { item: "paper", qty: 100, size: { h: 8.5, w: 11, uom: "in" }, status: "D" },
   { item: "planner", qty: 75, size: { h: 22.85, w: 30, uom: "cm" }, status: "D" },
   { item: "postcard", qty: 45, size: { h: 10, w: 15.25, uom: "cm" }, status: "A" }
]);
```

## 检索集合中的所有文档

如果想检索集合中的**所有文档**，可以在find方法中传一个**空文档**作为查询过滤条件。查询过滤参数确定选择条件：

```javascript
db.inventory.find( {} )
```

上述操作对应如下SQL语句：

```javascript
SELECT * FROM inventory
```

有关该方法语法的更多信息，请参阅 [find()](https://docs.mongodb.com/v4.0/reference/method/db.collection.find/#db.collection.find)。

## 等值查询

在[查询过滤文档](https://docs.mongodb.com/manual/core/document/#std-label-document-query-filter)中使用\*\*<字段>:<值>\*\*表达式实现等值查询：

```javascript
{ <field1>: <value1>, ... }
```

下面的案例返回inventory**集合中**status**等于**"D"\*\*的所有文档:

```javascript
db.inventory.find( { status: "D" } )
```

上述操作对应如下SQL语句：

```javascript
SELECT * FROM inventory WHERE status = "D"
```

## 查询条件中使用查询操作符

[查询过滤文档](https://docs.mongodb.com/manual/core/document/#std-label-document-query-filter)中可以使用[查询操作符](https://docs.mongodb.com/manual/reference/operator/query/)来指定多个条件，格式如下:

```javascript
{ <field1>: { <operator1>: <value1> }, ... }
```

下面的案例返回**inventory**集合中**status**等于\*\*"A"**或**"D"\*\*的所有文档。

```javascript
db.inventory.find( { status: { $in: [ "A", "D" ] } } )
```

> Note:
>
> 尽管可以使用[$or](https://docs.mongodb.com/manual/reference/operator/query/or/#mongodb-query-op.-or)操作符来满足上述需求，但是在对相同字段进行等值检索的时候更建议使用[$in](https://docs.mongodb.com/manual/reference/operator/query/in/#mongodb-query-op.-in)。

上述操作对应如下SQL:

```javascript
SELECT * FROM inventory WHERE status in ("A", "D")
```

有关**MongoDB**查询运算符的完整列表，请参考[查询和映射操作符](https://docs.mongodb.com/v4.0/reference/operator/query/)

## AND条件

可以指定文档中的多个字段作为查询条件。在查询语句中使用AND连接多个查询条件来检索集合中满足所有查询条件的文档。

下面的案例返回**inventory**集合中**status**等于\*\*"A" **并且**qty\*\*小于([$lt](https://docs.mongodb.com/manual/reference/operator/query/lt/#mongodb-query-op.-lt))**30**的所有文档:

```javascript
db.inventory.find( { status: "A", qty: { $lt: 30 } } )
```

上述操作对应如下SQL:

```javascript
SELECT * FROM inventory WHERE status = "A" AND qty < 30
```

关于MongoDB的比较操作符可以参考[比较操作符](https://docs.mongodb.com/v4.0/reference/operator/query-comparison/#query-selectors-comparison)

## OR条件

使用[$or](https://docs.mongodb.com/v4.0/reference/operator/query/or/#op._S_or)运算符，可以指定一个联合查询，该查询将每个子句与逻辑 OR 连接起来，以便查询选择集合中至少匹配一个条件的文档。

下面的案例返回inventory集合中**status**等于\*\*"A" **或者**qty\*\*小于([$lt](https://docs.mongodb.com/manual/reference/operator/query/lt/#mongodb-query-op.-lt))30的所有文档。

```javascript
db.inventory.find( { $or: [ { status: "A" }, { qty: { $lt: 30 } } ] } )
```

上述操作对应如下SQL:

```javascript
SELECT * FROM inventory WHERE status = "A" OR qty < 30
```

> Note:
>
> 使用[比较操作符](https://docs.mongodb.com/v4.0/reference/operator/query-comparison/#query-selectors-comparison)的查询受[Type Bracketing](https://docs.mongodb.com/v4.0/reference/method/db.collection.find/#type-bracketing)的约束。

## 同时使用AND和OR条件

下面的案例返回inventory集合中**status**等于\*\*"A" **并且**qty**小于 (**[**$lt**](https://docs.mongodb.com/manual/reference/operator/query/lt/#mongodb-query-op.-lt)**) 30或者**item\*\* 是以**p**字符开头的所有文档。

```javascript
db.inventory.find( {
     status: "A",
     $or: [ { qty: { $lt: 30 } }, { item: /^p/ } ]
} )
```

上述操作对应如下SQL:

```javascript
SELECT * FROM inventory WHERE status = "A" AND ( qty < 30 OR item LIKE "p%")
```

> Note:
>
> MongoDB支持正则表达式操作符[$regex](https://docs.mongodb.com/manual/reference/operator/query/regex/#mongodb-query-op.-regex)来做字符串模式匹配。

## 其他查询教程

其他查询案例:

* [嵌套文档查询](https://docs.mongodb.com/manual/tutorial/query-embedded-documents/)
* [数组查询](https://docs.mongodb.com/manual/tutorial/query-arrays/)
* [数组中的嵌套文档查询](https://docs.mongodb.com/manual/tutorial/query-array-of-documents/)
* [查询语句中返回指定字段](https://docs.mongodb.com/manual/tutorial/project-fields-from-query-results/)
* [查询Null或者不存在的字段](https://docs.mongodb.com/manual/tutorial/query-for-null-fields/)

## 行为

**游标**

使用 [db.collection.find()](https://docs.mongodb.com/v4.0/reference/method/db.collection.find/#db.collection.find)方法返回检索到文档的一个[游标](https://docs.mongodb.com/v4.0/tutorial/iterate-a-cursor/)。

**读隔离**

*新增加于MongoDB3.2版本*

对于[副本集](https://docs.mongodb.com/manual/replication/)或者[分片副本集](https://docs.mongodb.com/manual/sharding/)的查询，读关注允许客户端选择读的隔离级别。更多的信息可以查看[Read Concern](https://docs.mongodb.com/v4.0/reference/read-concern/)

### 其它的方法

下面的方法也可以从集合中查询文档:

* [db.collection.findOne](https://docs.mongodb.com/v4.0/reference/method/db.collection.findOne/#db.collection.findOne)
* 在[聚合管道](https://docs.mongodb.com/v4.0/core/aggregation-pipeline/)中，[$match](https://docs.mongodb.com/v4.0/reference/operator/aggregation/match/#pipe._S_match)管道阶段提供了MongoDB的查询过滤。

> Note:
>
> [db.collection.findOne](https://docs.mongodb.com/v4.0/reference/method/db.collection.findOne/#db.collection.findOne) 方法提供了返回单个文档的读操作。
>
> 实际上，[db.collection.findOne](https://docs.mongodb.com/v4.0/reference/method/db.collection.findOne/#db.collection.findOne) 就是[db.collection.find()](https://docs.mongodb.com/v4.0/reference/method/db.collection.find/#db.collection.find) 方法后面加了个限制条数1。

原文链接：<https://docs.mongodb.com/manual/tutorial/query-documents/>

译者：张芷嘉


# 在mongo Shell中迭代游标

**在本页面**

* [手动迭代游标](#游标)
* [迭代器索引](#索引)
* [游标行为](#行为)
* [游标信息](#信息)

方法返回一个游标。 要访问文档，您需要迭代游标。 但是，在mongo shell中，如果未使用**var**关键字将返回的游标分配给变量，则该游标将自动迭代多达20次，以打印结果中的前20个文档。

以下示例描述了手动迭代游标以访问文档或使用迭代器索引的方法。

## **手动迭代游标**

在[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell中，当使用**var**关键字将[`find()`](https://docs.mongodb.com/master/reference/method/db.collection.find/#db.collection.find) 方法返回的游标分配给变量时，游标不会自动进行迭代。

您可以在shell程序中调用cursor变量以进行多达20次迭代并打印匹配的文档，如以下示例所示：

```
var myCursor = db.users.find( { type: 2 } );

myCursor
```

您还可以使用游标方法[`next()`](https://docs.mongodb.com/master/reference/method/cursor.next/#cursor.next)来访问文档，如以下示例所示：

```
var myCursor = db.users.find( { type: 2 } );

 while (myCursor.hasNext())   
  printjson(myCursor.next());
 }
```

作为一种替代的打印操作，请考虑使用`printjson()`辅助方法替换`print(tojson())`：

```
var myCursor = db.users.find( { type: 2 } );

while (myCursor.hasNext()) {
   printjson(myCursor.next());
}
```

您可以使用游标方法[`forEach()`](https://docs.mongodb.com/master/reference/method/cursor.forEach/#cursor.forEach)来迭代游标并访问文档，如下例所示:

```
var myCursor =  db.users.find( { type: 2 } );

myCursor.forEach(printjson);
```

有关游标方法的更多信息，请参阅[JavaScript游标方法](https://docs.mongodb.com/manual/reference/method/#js-query-cursor-methods)和 [driver](https://docs.mongodb.com/ecosystem/drivers)程序文档。

## **迭代器索引**

在 [`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell中，可以使用 [`toArray()`](https://docs.mongodb.com/master/reference/method/cursor.toArray/#cursor.toArray) 方法来迭代游标并以数组形式返回文档，如下所示：

```
var myCursor = db.inventory.find( { type: 2 } );
var documentArray = myCursor.toArray();
var myDocument = documentArray[3];
```

[`toArray()`](https://docs.mongodb.com/master/reference/method/cursor.toArray/#cursor.toArray) 方法将游标返回的所有文档加载到**RAM**中； [`toArray()`](https://docs.mongodb.com/master/reference/method/cursor.toArray/#cursor.toArray) 方法耗尽游标。

另外，某些[驱动](https://docs.mongodb.com/ecosystem/drivers)程序通过使用游标上的索引(即**cursor \[index]**)来提供对文档的访问。 这是先调用[`toArray()`](https://docs.mongodb.com/master/reference/method/cursor.toArray/#cursor.toArray) 方法，然后在结果数组上使用索引的快捷方式。

考虑以下示例：

```
var myCursor = db.users.find( { type: 2 } );
var myDocument = myCursor[1];
```

\*\*myCursor \[1]\*\*等效于以下示例：

```
myCursor.toArray() [1];
```

## 游标行为

### 关闭非活动游标

默认情况下，服务器将在闲置10分钟后或客户端用尽光标后自动关闭游标。 要在mongo shell中覆盖此行为，可以使用[`cursor.noCursorTimeout()`](https://docs.mongodb.com/manual/reference/method/cursor.noCursorTimeout/#cursor.noCursorTimeout)方法：

```
var myCursor = db.users.find().noCursorTimeout();
```

设置**noCursorTimeout**选项后，您必须使用[`cursor.close()`](https://docs.mongodb.com/master/reference/method/cursor.close/#cursor.close)手动关闭游标，或者用尽游标的结果。

有关设置**noCursorTimeout**选项的信息，请参见驱动程序文档。

### 游标隔离

当游标返回文档时，其他操作可能会与查询交错。

### 光标批次

MongoDB服务器批量返回查询结果。批处理中的数据量不会超过[最大BSON文档大小](https://docs.mongodb.com/master/reference/limits/#limit-bson-document-size)。若要覆盖批处理的默认大小，请参见[`batchSize()`](https://docs.mongodb.com/master/reference/method/cursor.batchSize/#cursor.batchSize) 和 [`limit()`](https://docs.mongodb.com/master/reference/method/cursor.limit/#cursor.limit).

3.4版中的新增功能：[`find()`](https://docs.mongodb.com/master/reference/method/db.collection.find/#db.collection.find), [`aggregate()`](https://docs.mongodb.com/master/reference/method/db.collection.aggregate/#db.collection.aggregate), [`listIndexes`](https://docs.mongodb.com/master/reference/command/listIndexes/#dbcmd.listIndexes), 和 [`listCollections`](https://docs.mongodb.com/master/reference/command/listCollections/#dbcmd.listCollections)类型的操作每批返回最多16 MB。 [`batchSize()`](https://docs.mongodb.com/master/reference/method/cursor.batchSize/#cursor.batchSize) 可以强制使用较小的限制，但不能强制使用较大的限制。

默认情况下，`find()`和`aggregate()`操作的初始批处理大小为101个文档。随后针对结果游标发出的[`getMore`](https://docs.mongodb.com/master/reference/command/getMore/#dbcmd.getMore)操作没有默认的批处理大小，因此它们仅受16 MB消息大小的限制。

对于包含不带索引的排序操作的查询，服务器必须在返回任何结果之前将所有文档加载到内存中以执行排序。

当您遍历游标并到达返回批处理的末尾时，如果还有更多结果，[`cursor.next()`](https://docs.mongodb.com/master/reference/method/cursor.next/#cursor.next) 将执行getMore操作以检索下一个批处理。要查看在迭代游标时批处理中剩余多少文档，可以使用[`objsLeftInBatch()`](https://docs.mongodb.com/master/reference/method/cursor.objsLeftInBatch/#cursor.objsLeftInBatch)方法，如以下示例所示：

```
var myCursor = db.inventory.find();

var myFirstDocument = myCursor.hasNext() ? myCursor.next() : null;

myCursor.objsLeftInBatch();
```

## 游标信息

[`db.serverStatus()`](https://docs.mongodb.com/master/reference/method/db.serverStatus/#db.serverStatus) 方法返回包含度量标准字段的文档。 指标字段包含一个带有以下信息的[`metrics.cursor`](https://docs.mongodb.com/master/reference/command/serverStatus/#serverstatus.metrics.cursor) 字段：

* 自上次服务器重新启动以来超时的游标数
* 设置了选项[`DBQuery.Option.noTimeout`](https://docs.mongodb.com/master/reference/method/cursor.addOption/#DBQuery.Option.noTimeout)的打开游标的数量，以防止一段时间不活动后发生超时
* “固定”打开游标的数量
* 打开的游标总数

考虑以下示例，该示例调用[`db.serverStatus()`](https://docs.mongodb.com/master/reference/method/db.serverStatus/#db.serverStatus) 方法并从结果中访问索引字段，然后从指标字段访问游标字段：

```
db.serverStatus().metrics.cursor
```

结果是以下文档：

```
{
   "timedOut" : <number>
   "open" : {
      "noTimeout" : <number>,
      "pinned" : <number>,
      "total" : <number>
   }
}
```

另可参考：

[db.serverStatus()](https://docs.mongodb.com/manual/reference/method/db.serverStatus/#db.serverStatus)

译者：杨帅

校对：杨帅


# 从查询返回的项目字段

默认情况下，MongoDB的查询语句返回匹配到文档的所有字段，为了限制MongoDB返回给应用的数据，可以通过[projection](https://docs.mongodb.com/v4.0/reference/glossary/#term-projection)文档来指定或限制返回的字段。

本文提供了使用mongo shell中[db.collection.find()](https://docs.mongodb.com/v4.0/reference/method/db.collection.find/#db.collection.find)方法映射查询的案例。案例中使用的**inventory**集合数据可以通过下面的语句产生。

```javascript
db.inventory.insertMany( [
  { item: "journal", status: "A", size: { h: 14, w: 21, uom: "cm" }, instock: [ { warehouse: "A", qty: 5 } ] },
  { item: "notebook", status: "A",  size: { h: 8.5, w: 11, uom: "in" }, instock: [ { warehouse: "C", qty: 5 } ] },
  { item: "paper", status: "D", size: { h: 8.5, w: 11, uom: "in" }, instock: [ { warehouse: "A", qty: 60 } ] },
  { item: "planner", status: "D", size: { h: 22.85, w: 30, uom: "cm" }, instock: [ { warehouse: "A", qty: 40 } ] },
  { item: "postcard", status: "A", size: { h: 10, w: 15.25, uom: "cm" }, instock: [ { warehouse: "B", qty: 15 }, { warehouse: "C", qty: 35 } ] }
]);
```

## 返回匹配文档中的所有字段

如果没有特别指定[projection](https://docs.mongodb.com/manual/reference/glossary/#std-term-projection), [db.collection.find()](https://docs.mongodb.com/v4.0/reference/method/db.collection.find/#db.collection.find)方法将会返回匹配文档的所有字段。

下面的案例返回**inventory**集合中**status**等于\*\*"A"\*\*的文档的所有字段。

```javascript
db.inventory.find( { status: "A" } )
```

上述操作等价于下面的标准SQL:

```javascript
SELECT * from inventory WHERE status = "A"
```

## 仅返回指定字段和\_id字段

映射会返回在映射文档中显示设置为**1**的字段。

下面的案例返回所有检索到文档中**item, status, \_id**三个字段。

```javascript
db.inventory.find( { status: "A" }, { item: 1, status: 1 } )
```

上述操作等价于下面的标准SQL:

```javascript
SELECT _id, item, status from inventory WHERE status = "A"
```

## 去除\_id字段

可以通过在映射文档中&#x5C06;**\_id**字段设置为**0**来从结果集中去除 **\_id**字段，就像下面的例子:

```javascript
db.inventory.find( { status: "A" }, { item: 1, status: 1, _id: 0 } )
```

上述操作等价于下面的标准SQL:

```javascript
SELECT item, status from inventory WHERE status = "A"
```

> Note:
>
> 除\_id字段外，不能在映射文档中同时使用包含和去除语句。

## 去除指定字段

可以使用映射来排除特定字段，而不是在匹配文档中列出要返回的字段。

下面的案例返回匹配文档中除**status** 和 **instock** 字段之外的所有字段：

```javascript
db.inventory.find( { status: "A" }, { status: 0, instock: 0 } )
```

> Note:
>
> 除\_id字段外，不能在映射文档中同时使用包含和去除语句。

## 返回嵌套文档中的指定字段

通过[点号](https://docs.mongodb.com/v4.0/core/document/#document-dot-notation)引用嵌套文档字段并且在映射文档中将该字段设置为**1**来实现返回嵌套文档中的指定字段。

下面的案例返回

* **\_id**字段(默认返回)
* **item**字段
* **status**字段
* 文档**size**中的**uom**字段

**uom**字段是**size**嵌套文档中的字段.

```javascript
db.inventory.find(
   { status: "A" },
   { item: 1, status: 1, "size.uom": 1 }
)
```

## 去除嵌套文档中的指定字段

通过[点号](https://docs.mongodb.com/v4.0/core/document/#document-dot-notation)引用嵌套文档字段并且在映射文档中将该字段设置为**0**来实现去除嵌套文档中的指定字段。

下面的案例返回匹配文档中除嵌套文档**size**中的**uom**字段外的所有字段。

```javascript
db.inventory.find(
   { status: "A" },
   { "size.uom": 0 }
)
```

## 映射数组中的嵌套文档的指定字段

通过使用[点号](https://docs.mongodb.com/v4.0/core/document/#document-dot-notation)来映射数组中嵌套文档的指定字段。

下面案例返回:

* **\_id**字段(默认返回)
* **item**字段
* **status**字段
* 数组字段**instock**中的嵌套文档中的**qty**字段

```javascript
db.inventory.find( { status: "A" }, { item: 1, status: 1, "instock.qty": 1 } )
```

## 映射返回数组中指定的数组元素

对于数组字段，MongoDB 提供了以下用于操作数组的映射运算符:[$elemMatch](https://docs.mongodb.com/v4.0/reference/operator/projection/elemMatch/#proj._S_elemMatch),[$slice](https://docs.mongodb.com/v4.0/reference/operator/projection/slice/#proj._S_slice),[$](https://docs.mongodb.com/v4.0/reference/operator/projection/positional/#proj._S_)

下面的案例使用[$slice](https://docs.mongodb.com/manual/reference/operator/projection/slice/#mongodb-projection-proj.-slice)映射操作符返回数组字段**instock**中最后的元素:

```javascript
db.inventory.find( { status: "A" }, { item: 1, status: 1, instock: { $slice: -1 } } )
```

[$elemMatch](https://docs.mongodb.com/manual/reference/operator/projection/elemMatch/#mongodb-projection-proj.-elemMatch),[$slice](https://docs.mongodb.com/manual/reference/operator/projection/slice/#mongodb-projection-proj.-slice),[$](https://docs.mongodb.com/manual/reference/operator/projection/positional/#mongodb-projection-proj.-)是将指定元素映射到返回数组中的唯一方法。

举个例子，不能使用数组下标来映射指定的数组元素。例如:\*\*{ "instock.0": 1 }\*\*映射不会用第一个元素来映射数组。

参考:

[Query Documents](https://docs.mongodb.com/v4.0/tutorial/query-documents/)

3323

原文链接：<https://docs.mongodb.com/manual/tutorial/project-fields-from-query-results/>

译者：张芷嘉


# 查询嵌入式文档数组

本文提供了使用 mongo shell 中的[db.collection.find()](https://docs.mongodb.com/v4.0/reference/method/db.collection.find/#db.collection.find) 方法对数组中嵌套文档进行查询操作的示例。

可以通过下面的语句生成本文使用的**inventory**集合。

```javascript
db.inventory.insertMany( [
   { item: "journal", instock: [ { warehouse: "A", qty: 5 }, { warehouse: "C", qty: 15 } ] },
   { item: "notebook", instock: [ { warehouse: "C", qty: 5 } ] },
   { item: "paper", instock: [ { warehouse: "A", qty: 60 }, { warehouse: "B", qty: 15 } ] },
   { item: "planner", instock: [ { warehouse: "A", qty: 40 }, { warehouse: "B", qty: 5 } ] },
   { item: "postcard", instock: [ { warehouse: "B", qty: 15 }, { warehouse: "C", qty: 35 } ] }
]);
```

### 查询数组中的嵌套文档

下面的案例返回**instock**数组中元素等于指定文档的的所有文档:

```javascript
db.inventory.find( { "instock": { warehouse: "A", qty: 5 } } )
```

当对整个嵌套文档使用等值匹配的时候是要求精确匹配指定文档，包括字段顺序。比如，下面的语句并没有查询到**inventory**集合中的任何文档：

```javascript
db.inventory.find( { "instock": { qty: 5, warehouse: "A" } } )
```

### 指定查询条件在数组嵌套文档的字段上

#### 指定查询条件在数组中嵌套文档的字段上

如果你不知道数组中嵌套文档的下标，使用\*\*(.)\*\*号连接数组字段的名字和数组中嵌套文档中字段的名字。

下面的案例返回**instock**数组中最少有一个嵌套文档包含字段**qty**的值小于等于**20**的所有文档 :

```javascript
db.inventory.find( { 'instock.qty': { $lte: 20 } } )
```

#### 使用数组下标查询数组中嵌套文档中的字段

使用[dot notation](https://docs.mongodb.com/v4.0/reference/glossary/#term-dot-notation)，可以指定查询条件在数组中指定数组下标的嵌套文档的字段上面。数组下标从0开始。

> Note:
>
> 当查询使用点号的时候，字段和索引必须在引号内。

下面案例返回**instock**数组中的第一个元素是包含字段**qty**小于等于**20**的文档的所有文档：

```javascript
db.inventory.find( { 'instock.0.qty': { $lte: 20 } } )
```

### 指定多个条件检索数组嵌套文档

当对数组中嵌套文档中多个字段指定查询条件的时候，可以在查询语句中指定单个文档满足这些查询条件或者是数组中多个文档联合(单个文档)满足这些查询条件。

#### 单个嵌套文档中的字段满足多个查询条件

使用[$elemMatch](https://docs.mongodb.com/v4.0/reference/operator/query/elemMatch/#op._S_elemMatch)操作符为数组中的嵌套文档指定多个查询条件，最少一个嵌套文档同时满足所有的查询条件。

下面的案例返回**instock**数组中最少有一个嵌套文档包含**qty**等于**5**同时**warhouse**等于**A**的所有文档：

```javascript
db.inventory.find( { "instock": { $elemMatch: { qty: 5, warehouse: "A" } } } )
```

下面的案例返回**instock**数组中最少一个嵌套文档包含字段**qty**大于**10**并且小于**20**的所有文档:

```javascript
db.inventory.find( { "instock": { $elemMatch: { qty: { $gt: 10, $lte: 20 } } } } )
```

#### 多个元素联合满足查询条件

如果数组字段上的联合查询条件没有使用 [$elemMatch](https://docs.mongodb.com/v4.0/reference/operator/query/elemMatch/#op._S_elemMatch)运算符，查询返回数组字段中多个元素联合满足所有的查询条件的所有文档。

下面的案例返回数组字段**instock**中嵌套文档中**qty**字段大于**10**并且数组中其它嵌套文档(不一定是同一个嵌套文档)**qty**字段小于等于**20**的所有文档:

```javascript
db.inventory.find( { "instock.qty": { $gt: 10,  $lte: 20 } } )
```

下面的案例返回数组字段**instock**中最少一个嵌套文档包含**qty**等于**5**并且最少一个嵌套文档(不一定是同一个嵌套文档)包含**warehouse**字段等于**A**的所有文档:

```javascript
db.inventory.find( { "instock.qty": 5, "instock.warehouse": "A" } )
```

### 其它查询导航

#### 其它查询案例:

* [数组查询](https://docs.mongodb.com/v4.0/tutorial/query-arrays/)
* [文档查询](https://docs.mongodb.com/v4.0/tutorial/query-documents/)
* [嵌套文档查询](https://docs.mongodb.com/v4.0/tutorial/query-embedded-documents/)

原文链接：<https://docs.mongodb.com/manual/tutorial/query-array-of-documents/>

译者：张芷嘉


# 查询数组

本文提供了使用mongo shell中[db.collection.find()](https://docs.mongodb.com/v4.0/reference/method/db.collection.find/#db.collection.find) 方法查询数组的操作案例。案例中使用的**inventory**集合数据可以通过下面的语句产生。

```javascript
db.inventory.insertMany([
   { item: "journal", qty: 25, tags: ["blank", "red"], dim_cm: [ 14, 21 ] },
   { item: "notebook", qty: 50, tags: ["red", "blank"], dim_cm: [ 14, 21 ] },
   { item: "paper", qty: 100, tags: ["red", "blank", "plain"], dim_cm: [ 14, 21 ] },
   { item: "planner", qty: 75, tags: ["blank", "red"], dim_cm: [ 22.85, 30 ] },
   { item: "postcard", qty: 45, tags: ["blue"], dim_cm: [ 10, 15.25 ] }
]);
```

## 数组查询

数组字段做等值查询的时候，使用查询文档\*\*{:}\*\*其中 \*\*\*\*是要精确匹配的数组，包含元素的顺序。

下面的案例返回inventory集合中数组字段**tags**值是**只包含两个元素"red","blank"并且有指定顺序的数组**的所有文档:

```javascript
db.inventory.find( { tags: ["red", "blank"] } )
```

如果想检索数组中包含\*\*"red"**,**"blank"\*\*两个元素并且不在乎元素顺序或者数组中是否有其它元素。可以使用[$all](https://docs.mongodb.com/manual/reference/operator/query/all/#mongodb-query-op.-all)操作符:

```javascript
db.inventory.find( { tags: { $all: ["red", "blank"] } } )
```

## 查询数组中的元素

检索数组字段中至少一个元素等于指定的值，使用\*\*:**的形式，其中**\*\*是一个元素值。

下面的案例返回inventory集合中数组字段**tags**中有一个元素的值是\*\*"red"\*\*的所有文档:

```javascript
db.inventory.find( { tags: "red" } )
```

对数组中的元素进行检索的时候，可以使用[查询操作符](https://docs.mongodb.com/manual/reference/operator/query/#std-label-query-selectors)在[查询过滤文档](https://docs.mongodb.com/manual/core/document/#std-label-document-query-filter)中。

```javascript
{ <array field>: { <operator1>: <value1>, ... } }
```

下面的案例返回inventory集合中数组字段**dim\_cm**中最少有一个元素的值大于**25**的所有文档。

```javascript
db.inventory.find( { dim_cm: { $gt: 25 } } )
```

## 多条件查询数组中的元素

使用多条件查询数组中的元素时，可以在查询语句中指定单个数组元素满足所有查询条件还是多个数组中的元素联合满足所有条件。

#### 使用多条件查询数组中的元素

下面的案例返回inventory集合中数组字段**dim\_cm**中单个元素同时满足大于15并且小于20，或者一个元素满足大于**15**，另外一个元素小于**20**的所有文档:

```javascript
db.inventory.find( { dim_cm: { $gt: 15, $lt: 20 } } )
```

#### 数组中的元素同时满足多个查询条件

使用[$elemMatch](https://docs.mongodb.com/v4.0/reference/operator/query/elemMatch/#op._S_elemMatch)来指定多个查询条件在数组中的元素上，数组中最少一个元素同时满足所有的查询条件。

下面的案例返回数组字段**dim\_cm**中最少一个元素同时满足大于([$gt](https://docs.mongodb.com/v4.0/reference/operator/query/gt/#op._S_gt))**22** 并且 小于([$lt](https://docs.mongodb.com/v4.0/reference/operator/query/lt/#op._S_lt)) **30**:

```javascript
db.inventory.find( { dim_cm: { $elemMatch: { $gt: 22, $lt: 30 } } } )
```

#### 使用数组下标查询数组中的元素

使用[点号](https://docs.mongodb.com/v4.0/reference/glossary/#term-dot-notation)，可以为数组中指定下标的元素指定查询条件，数组下标从0开始。

> Note:
>
> 当使用点号的时候，字段和嵌套文档字段必须在引号内

下面的案例返回数组字段**dim\_cm**中第二个元素大于**25**的所有文档:

```javascript
db.inventory.find( { "dim_cm.1": { $gt: 25 } } )
```

#### 使用数组长度来检索

使用[$size](https://docs.mongodb.com/v4.0/reference/operator/query/size/#op._S_size)操作符通过数组中的元素个数来进行检索。

下面的查询返回数组字段**tags**中有三个元素的所有文档 :

```javascript
db.inventory.find( { "tags": { $size: 3 } } )
```

### 其它查询导航

#### 其它查询案例:

* [文档查询](https://docs.mongodb.com/v4.0/tutorial/query-documents/)
* [嵌套文档查询](https://docs.mongodb.com/v4.0/tutorial/query-embedded-documents/)
* [数组嵌套文档查询](https://docs.mongodb.com/v4.0/tutorial/query-array-of-documents/)

原文链接：<https://docs.mongodb.com/manual/tutorial/query-arrays/>

译者：张芷嘉


# 查询空字段或缺少字段

在MongoDB中不同的查询操作符对于**null**值处理方式不同。

本文提供了使用 mongo shell 中的[db.collection.find()](https://docs.mongodb.com/v4.0/reference/method/db.collection.find/#db.collection.find) 方法查询**null**值的操作案例。案例中使用的**inventory**集合数据可以通过下面的语句产生。

```javascript
db.inventory.insertMany([
   { _id: 1, item: null },
   { _id: 2 }
])
```

## 等值匹配

当使用\*\*{item:null}**作为查询条件的时候，返回的是**item**字段值为**null**的文档或者不包含**item\*\*字段的文档。

```javascript
db.inventory.find( { item: null } )
```

该查询返回inventory集合中的所有文档。

## 类型检查

当使用\*\*{item:{$type:10}}\*\*作为查询条件的时候，仅返回item字段值为null的文档。**item**字段的值是[BSON TYPE](https://docs.mongodb.com/v4.0/reference/bson-types/) **NULL**(type number 10)

```javascript
db.inventory.find( { item : { $type: 10 } } )
```

该查询仅返回**item**字段值为**null**的文档。

## 存在检查

当使用\*\*{item:{$exists:false}}**作为查询条件的时候，返回不包含**item\*\*字段的文档。

```javascript
db.inventory.find( { item : { $exists: false } } )
```

该查询仅返回不包含item字段的文档。

## 相关文档

[$type](https://docs.mongodb.com/manual/reference/operator/query/type/#mongodb-query-op.-type)

[$exists](https://docs.mongodb.com/manual/reference/operator/query/exists/#mongodb-query-op.-exists)

原文链接：<https://docs.mongodb.com/manual/tutorial/query-for-null-fields/>

译者：张芷嘉


# 查询嵌入/嵌套文档

本文提供了使用mongo shell中[db.collection.find()](https://docs.mongodb.com/v4.0/reference/method/db.collection.find/#db.collection.find) 方法查询嵌套文档的操作案例。案例中使用的**inventory**集合数据可以通过下面的语句产生。

```javascript
db.inventory.insertMany( [
   { item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
   { item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in" }, status: "A" },
   { item: "paper", qty: 100, size: { h: 8.5, w: 11, uom: "in" }, status: "D" },
   { item: "planner", qty: 75, size: { h: 22.85, w: 30, uom: "cm" }, status: "D" },
   { item: "postcard", qty: 45, size: { h: 10, w: 15.25, uom: "cm" }, status: "A" }
]);
```

## 嵌套文档查询

对嵌套文档的字段做**等值**查询的时候，使用[query filter document](https://docs.mongodb.com/manual/core/document/#std-label-document-query-filter) **{:}** 其中\*\*\*\*是等值匹配的文档。

下面的案例返回inventory集合中**size**字段的值等于\*\*文档{ h: 14, w: 21, uom: "cm" }\*\*的所有文档。

```javascript
db.inventory.find( { size: { h: 14, w: 21, uom: "cm" } } )
```

对嵌套文档整体做**等值匹配**的时候，要求的是对指定\*\*\*\*文档的精确匹配，包含字段顺序。

下面的案例无法查询到任何文档。

```javascript
db.inventory.find(  { size: { w: 21, h: 14, uom: "cm" } }  )
```

## 嵌套文档中的字段

查询嵌套文档中的字段，使用[dot notation](https://docs.mongodb.com/v4.0/reference/glossary/#term-dot-notation)**("field.nestedField")**.

> Note:
>
> 当在查询语句中使用"."，字段和嵌套文档字段必须在引号内。

#### 嵌套文档中的字段等值查询

下面的案例返回inventory集合中**size字段中嵌套文档字段uom**值等于\*\*"in"\*\*的所有文档。

```javascript
db.inventory.find( { "size.uom": "in" } )
```

#### 使用查询操作符查询

在[query filter document](https://docs.mongodb.com/v4.0/core/document/#document-query-filter)中可以使用[查询操作符](https://docs.mongodb.com/v4.0/reference/operator/query/#query-selectors)指定多个查询条件，格式如下:

```javascript
{ <field1>: { <operator1>: <value1> }, ... }
```

下面的查询语句在字段**size**中的嵌套文档字段**h**上面使用([$lt](https://docs.mongodb.com/v4.0/reference/operator/query/lt/#op._S_lt))操作符:

```javascript
db.inventory.find( { "size.h": { $lt: 15 } } )
```

#### 使用AND条件

下面的案例返回inventory集合中**size字段中嵌套文档字段h**值小于**15** 并且 **size字段中嵌套文档字段uom**值等于\*\*"in"\*\* 并且**status**字段等于\*\*"D"\*\*的所有文档。

```javascript
db.inventory.find( { "size.h": { $lt: 15 }, "size.uom": "in", status: "D" } )
```

### 其他查询导航

#### 其他查询案例:

* [文档查询](https://docs.mongodb.com/v4.0/tutorial/query-documents/)
* [数组查询](https://docs.mongodb.com/v4.0/tutorial/query-arrays/)
* [数组中嵌套文档查询](https://docs.mongodb.com/v4.0/tutorial/query-array-of-documents/)

原文链接：<https://docs.mongodb.com/manual/tutorial/query-embedded-documents/>

译者：张芷嘉


# 更新文档

此页面使用以下 [`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell方法：

* [db.collection.updateOne(<`filter`>, <`update`>, <`options`>)](https://docs.mongodb.com/manual/reference/method/db.collection.updateOne/#db.collection.updateOne)
* [db.collection.updateMany(<`filter`>, <`update`>, <`options`>)](https://docs.mongodb.com/manual/reference/method/db.collection.updateMany/#db.collection.updateMany)
* [db.collection.replaceOne(<`filter`>, <`update`>, <`options`>)](https://docs.mongodb.com/manual/reference/method/db.collection.replaceOne/#db.collection.replaceOne)

此页面上的示例使用库存收集。 要创建和/或填充清单集合，请运行以下命令：

此页上的示例使用**inventory**集合。要创建和/或填充**inventory**集合，请运行以下操作:

```
db.inventory.insertMany( [
   { item: "canvas", qty: 100, size: { h: 28, w: 35.5, uom: "cm" }, status: "A" },
   { item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
   { item: "mat", qty: 85, size: { h: 27.9, w: 35.5, uom: "cm" }, status: "A" },
   { item: "mousepad", qty: 25, size: { h: 19, w: 22.85, uom: "cm" }, status: "P" },
   { item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in" }, status: "P" },
   { item: "paper", qty: 100, size: { h: 8.5, w: 11, uom: "in" }, status: "D" },
   { item: "planner", qty: 75, size: { h: 22.85, w: 30, uom: "cm" }, status: "D" },
   { item: "postcard", qty: 45, size: { h: 10, w: 15.25, uom: "cm" }, status: "A" },
   { item: "sketchbook", qty: 80, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
   { item: "sketch pad", qty: 95, size: { h: 22.85, w: 30.5, uom: "cm" }, status: "A" }
] );
```

## 更新集合中的文档

为了更新文档，MongoDB提供了[更新操作符](https://docs.mongodb.com/manual/reference/operator/update)（例如[`$set`](https://docs.mongodb.com/master/reference/operator/update/set/#up._S_set)）来修改字段值。

要使用更新运算符，请将以下形式的更新文档传递给更新方法：

```sql
{
        <update operator>: { <field1>: <value1>, ... },
        <update operator>: { <field2>: <value2>, ... },
        ...
}
```

如果字段不存在，则某些更新操作符（例如[`$set`](https://docs.mongodb.com/master/reference/operator/update/set/#up._S_set)）将创建该字段。 有关详细信息，请参见各个更新操作员参考。

> **\[success] Note**
>
> **从MongoDB 4.2开始，MongoDB可以接受聚合管道来指定要进行的修改而不是更新文档。 有关详细信息，请参见方法参考页。**

### 更新单个文档

下面的示例在**inventory**集合上使用[`db.collection.updateOne()`](https://docs.mongodb.com/manual/reference/method/db.collection.updateOne/#db.collection.updateOne)方法更新项目等于“ **paper**”的第一个文档：

```
db.inventory.updateOne(
    { item: "paper" },
    {
        $set: { "size.uom": "cm", status: "P" }, 
        $currentDate: { lastModified: true }
    }
)
```

**更新操作：**

* 使用[`$set`](https://docs.mongodb.com/master/reference/operator/update/set/#up._S_set) 运算符将**size.uom**字段的值更新为“ **cm**”，将状态字段的值更新为“ **P**”，
* 使用[`$currentDate`](https://docs.mongodb.com/master/reference/operator/update/currentDate/#up._S_currentDate)运算符将**lastModified**字段的值更新为当前日期。 如果**lastModified**字段不存在，则[`$currentDate`](https://docs.mongodb.com/master/reference/operator/update/currentDate/#up._S_currentDate)将创建该字段。 有关详细信息，请参见[`$currentDate`](https://docs.mongodb.com/master/reference/operator/update/currentDate/#up._S_currentDate)。

### 更新多个文档

*3.2版中的新功能*

以下示例在清单集合上使用[`db.collection.updateMany()`](https://docs.mongodb.com/manual/reference/method/db.collection.updateMany/#db.collection.updateMany)方法来更新数量小于**50**的所有文档：

```
  db.inventory.updateMany( 
      { "qty": { $lt: 50 } },
      {  
          $set: { "size.uom": "in", status: "P" }, 
          $currentDate: { lastModified: true }  
      }
  )
```

**更新操作：**

* 使用[`$set`](https://docs.mongodb.com/master/reference/operator/update/set/#up._S_set)运算符将**size.uom**字段的值更新为“ **in**”，将状态字段的值更新为“ **P**”.
* 使用 [`$currentDate`](https://docs.mongodb.com/master/reference/operator/update/currentDate/#up._S_currentDate) 运算符将**lastModified**字段的值更新为当前日期。如果**lastModified**字段不存在，则[`$currentDate`](https://docs.mongodb.com/master/reference/operator/update/currentDate/#up._S_currentDate) 将创建该字段。有关详细信息，请参见[`$currentDate`](https://docs.mongodb.com/master/reference/operator/update/currentDate/#up._S_currentDate) 。

## 更换文档

要替换\*\*\_id\*\*字段以外的文档的全部内容，请将一个全新的文档作为第二个参数传递给[`db.collection.replaceOne()`](https://docs.mongodb.com/master/reference/method/db.collection.replaceOne/#db.collection.replaceOne)。

当替换一个文档时，替换文档必须只包含字段/值对;即不包括更新操作符表达式。

替换文档可以具有与原始文档不同的字段。在替换文档中，由于\*\*\_id**字段是不可变的，因此可以省略**\_id**字段。但是，如果您确实包含**\_id\*\*字段，则它必须与当前值具有相同的值。

下面的示例替换了**inventory**集合中的第一个文件，其中项为\*\*"paper"\*\*:

```
db.inventory.replaceOne(
   { item: "paper" },
   { item: "paper", instock: [ { warehouse: "A", qty: 60 }, { warehouse: "B", qty: 40 } ] }
)
```

## 行为

### 原子性

MongoDB中的所有写操作都是单个文档级别上的原子操作。有关MongoDB和原子性的更多信息，请参见原子性和事务。

### \_id Field

设置后，您将无法更新\*\*\_id**字段的值，也无法将现有文档替换为具有不同**\_id\*\*字段值的替换文档。

### 字段顺序

除以下情况外，MongoDB会在执行写操作后保留文档字段的顺序：

* **\_id**字段始终是文档中的第一个字段。
* 包含字段名称[`renaming`](https://docs.mongodb.com/master/reference/operator/update/rename/#up._S_rename) 的更新可能导致文档中字段的重新排序。

### 增补选项

如果[`updateOne()`](https://docs.mongodb.com/master/reference/method/db.collection.updateOne/#db.collection.updateOne), [`updateMany()`](https://docs.mongodb.com/master/reference/method/db.collection.updateMany/#db.collection.updateMany), or [`replaceOne()`](https://docs.mongodb.com/master/reference/method/db.collection.replaceOne/#db.collection.replaceOne) 包含**upsert：true**，并且没有文档与指定的过滤器匹配，则该操作将创建一个新文档并将其插入。 如果存在匹配的文档，则该操作将修改或替换一个或多个匹配的文档。

有关创建的新文档的详细信息，请参见各个方法的参考页。

### 写确认书

对于写入问题，您可以指定从MongoDB请求的写入操作的确认级别。 有关详细信息，请参见[写关注](https://docs.mongodb.com/manual/reference/write-concern/)。

另请参考：

* [Updates with Aggregation Pipeline](https://docs.mongodb.com/manual/tutorial/update-documents-with-aggregation-pipeline/)
* [db.collection.updateOne()](https://docs.mongodb.com/manual/reference/method/db.collection.updateOne/#db.collection.updateOne)
* [db.collection.updateMany()](https://docs.mongodb.com/manual/reference/method/db.collection.updateMany/#db.collection.updateMany)
* [db.collection.replaceOne()](https://docs.mongodb.com/manual/reference/method/db.collection.replaceOne/#db.collection.replaceOne)
* [Additional Methods](https://docs.mongodb.com/manual/reference/update-methods/#additional-updates)

译者：杨帅

校对：杨帅


# 更新方法

MongoDB提供了以下方法来更新集合中的文档：

|                                                                                                                                   |                                                                                                                                                                                                   |
| --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [db.collection.updateOne()](https://docs.mongodb.com/manual/reference/method/db.collection.updateOne/#db.collection.updateOne)    | 即使多个文档可能与指定的过滤器匹配，最多更新与指定的过滤器匹配的单个文档。 *3.2版中的新功能*                                                                                                                                                 |
| [db.collection.updateMany()](https://docs.mongodb.com/manual/reference/method/db.collection.updateMany/#db.collection.updateMany) | 更新所有与指定过滤器匹配的文档。 *3.2版中的新功能*                                                                                                                                                                      |
| [db.collection.replaceOne()](https://docs.mongodb.com/manual/reference/method/db.collection.replaceOne/#db.collection.replaceOne) | 即使多个文档可能与指定过滤器匹配，也最多替换一个与指定过滤器匹配的文档。 *3.2版中的新功能*                                                                                                                                                  |
| [db.collection.update()](https://docs.mongodb.com/manual/reference/method/db.collection.update/#db.collection.update)             | 更新或替换与指定过滤器匹配的单个文档，或更新与指定过滤器匹配的所有文档。 默认情况下，[db.collection.update()](https://docs.mongodb.com/manual/reference/method/db.collection.update/#db.collection.update)方法更新单个文档。 要更新多个文档，请使用**multi**选项。 |

## 附加方法

以下方法还可以更新集合中的文档：

* [db.collection.findOneAndReplace()](https://docs.mongodb.com/manual/reference/method/db.collection.findOneAndReplace/#db.collection.findOneAndReplace).
* [db.collection.findOneAndUpdate()](https://docs.mongodb.com/manual/reference/method/db.collection.findOneAndUpdate/#db.collection.findOneAndUpdate).
* [db.collection.findAndModify()](https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/#db.collection.findAndModify).
* [db.collection.save()](https://docs.mongodb.com/manual/reference/method/db.collection.save/#db.collection.save).
* [db.collection.bulkWrite()](https://docs.mongodb.com/manual/reference/method/db.collection.bulkWrite/#db.collection.bulkWrite).

有关更多方法和示例，请参见各个方法的参考页。

译者：杨帅

校对：杨帅


# 聚合管道更新

从MongoDB 4.2开始，您可以将聚合管道用于更新操作。 通过更新操作，聚合管道可以包括以下阶段：

|                                                                                                                 |                                                                                                                 |
| --------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| [$addFields](https://docs.mongodb.com/manual/reference/operator/aggregation/addFields/#pipe._S_addFields)       | [$set](https://docs.mongodb.com/manual/reference/operator/aggregation/set/#pipe._S_set)                         |
| [$project](https://docs.mongodb.com/manual/reference/operator/aggregation/project/#pipe._S_project)             | [$unset](https://docs.mongodb.com/manual/reference/operator/aggregation/unset/#pipe._S_unset)                   |
| [$replaceRoot](https://docs.mongodb.com/manual/reference/operator/aggregation/replaceRoot/#pipe._S_replaceRoot) | [$replaceWith](https://docs.mongodb.com/manual/reference/operator/aggregation/replaceWith/#pipe._S_replaceWith) |

使用聚合管道允许使用表达性更强的update语句，比如根据当前字段值表示条件更新，或者使用另一个字段的值更新一个字段。

## 例1

创建一个示例**students**学生集合（如果该集合当前不存在，则插入操作将创建该集合）：

```
db.students.insertMany([
   { _id: 1, test1: 95, test2: 92, test3: 90, modified: new Date("01/05/2020") },
   { _id: 2, test1: 98, test2: 100, test3: 102, modified: new Date("01/05/2020") },
   { _id: 3, test1: 95, test2: 110, modified: new Date("01/04/2020") }
])
```

要验证，请查询集合：

```
db.students.find()
```

以下[`db.collection.updateOne()`](https://docs.mongodb.com/manual/reference/method/db.collection.updateOne/#db.collection.updateOne)操作使用聚合管道使用\*\*\_id\*\*更新文档：**3**：

```
db.students.updateOne( { _id: 3 }, [ { $set: { "test3": 98, modified: "$$NOW"} } ] )
```

具体地说，管道包括[`$set`](https://docs.mongodb.com/master/reference/operator/aggregation/set/#pipe._S_set)阶段，该阶段将**test3**字段（并将其值设置为**98**）添加到文档中，并将修改后的字段设置为当前日期时间。 对于当前日期时间，该操作将聚合变量[`NOW`](https://docs.mongodb.com/master/reference/aggregation-variables/#variable.NOW) 用于（以访问变量，以\*\*$$\*\*为前缀并用引号引起来）。

要验证更新，您可以查询集合：

```
db.students.find().pretty()
```

## 例2

创建一个示例**students2**集合(如果该集合当前不存在，则插入操作将创建该集合):

```
db.students2.insertMany([
        { "_id" : 1, quiz1: 8, test2: 100, quiz2: 9, modified: new Date("01/05/2020") }, 
        { "_id" : 2, quiz2: 5, test1: 80, test2: 89, modified: new Date("01/05/2020") },
])
```

要验证，请查询集合：

```
db.students2.find()
```

以下[`db.collection.updateMany()`](https://docs.mongodb.com/master/reference/method/db.collection.updateMany/#db.collection.updateMany) 操作使用聚合管道来标准化文档的字段（即,集合中的文档应具有相同的字段）并更新修改后的字段：

```
db.students2.updateMany( {},
    [
        { $replaceRoot: { newRoot: 
            { $mergeObjects: [ { quiz1: 0, quiz2: 0, test1: 0, test2: 0 }, "$$ROOT" ] } 
    } },
        { $set: { modified: "$$NOW"}  }
    ]
)
```

具体来说，管道包括：

* [`$replaceRoot`](https://docs.mongodb.com/master/reference/operator/aggregation/replaceRoot/#pipe._S_replaceRoot) 阶段，带有 [`$mergeObjects`](https://docs.mongodb.com/master/reference/operator/aggregation/mergeObjects/#exp._S_mergeObjects)表达式，可为**quiz1**，**quiz2**，**test1**和**test2**字段设置默认值。 聚集变量[`ROOT`](https://docs.mongodb.com/master/reference/aggregation-variables/#variable.ROOT) 指的是正在修改的当前文档（以访问变量，以\*\*$$\*\*为前缀并用引号引起来）。 当前文档字段将覆盖默认值。
* [`$set`](https://docs.mongodb.com/master/reference/operator/aggregation/set/#pipe._S_set) 阶段用于将修改的字段更新到当前日期时间。 对于当前日期时间，该操作将聚合变量[NOW](/mongodb-crud-operations/update-documents/updates-with-aggregation-pipeline)用于（以访问变量，以\*\*$$\*\*为前缀并用引号引起来）。

要验证更新，您可以查询集合：

```
db.students2.find()
```

### 例3

创建一个示例**students3**集合（如果该集合当前不存在，则插入操作将创建该集合）：

```
db.students3.insert([
   { "_id" : 1, "tests" : [ 95, 92, 90 ], "modified" : ISODate("2019-01-01T00:00:00Z") },
   { "_id" : 2, "tests" : [ 94, 88, 90 ], "modified" : ISODate("2019-01-01T00:00:00Z") },
   { "_id" : 3, "tests" : [ 70, 75, 82 ], "modified" : ISODate("2019-01-01T00:00:00Z") }
]);
```

要验证，请查询集合：

```
db.students3.find()
```

以下 [`db.collection.updateMany()`](https://docs.mongodb.com/master/reference/method/db.collection.updateMany/#db.collection.updateMany)操作使用聚合管道以计算的平均成绩和字母成绩更新文档。

```
   db.students3.updateMany(
           { }, 
           [
               { $set: { average : { $trunc: [ { $avg: "$tests" }, 0 ] }, modified: "$$NOW" } },  
               { $set: { grade: { $switch: {                     
                               branches: [                     
                                           { case: { $gte: [ "$average", 90 ] }, then: "A" },     
                                           { case: { $gte: [ "$average", 80 ] }, then: "B" },  
                                           { case: { $gte: [ "$average", 70 ] }, then: "C" },   
                                           { case: { $gte: [ "$average", 60 ] }, then: "D" }   
                                       ],
                                           default: "F"   
           } } } }
           ]
   )
```

具体来说，管道包括：

* [`$set`](https://docs.mongodb.com/master/reference/operator/aggregation/set/#pipe._S_set)阶段来计算测试数组元素的截断平均值，并将修改后的字段更新为当前日期时间。 要计算截断的平均值，此阶段使用\*\*$avg**和**[**`$trunc`**](https://docs.mongodb.com/master/reference/operator/aggregation/trunc/#exp._S_trunc) **表达式。 对于当前日期时间，该操作将聚合变量**[**`NOW`**](https://docs.mongodb.com/master/reference/aggregation-variables/#variable.NOW) **用于(以访问变量，以**$$\*\*为前缀并用引号引起来).
* 一个[`$set`](https://docs.mongodb.com/master/reference/operator/aggregation/set/#pipe._S_set) 阶段，用于使用[`$switch`](https://docs.mongodb.com/master/reference/operator/aggregation/switch/#exp._S_switch) 表达式根据平均值添加年级字段。

  要验证更新，您可以查询集合：

  ```
  db.students3.find()
  ```

## 例4

创建一个示例**students4**集合(如果该集合当前不存在，则插入操作将创建该集合)：

```
db.students4.insertMany([
  { "_id" : 1, "quizzes" : [ 4, 6, 7 ] },
  { "_id" : 2, "quizzes" : [ 5 ] },
  { "_id" : 3, "quizzes" : [ 10, 10, 10 ] }
])
```

要验证，请查询集合：

```
 db.students4.find()
```

以下[`db.collection.updateOne()`](https://docs.mongodb.com/master/reference/method/db.collection.updateOne/#db.collection.updateOne)操作使用聚合管道将测验分数添加到具有\*\*\_id\*\*的文档中：**2**：

```
db.students4.updateOne( { _id: 2 },
  [ { $set: { quizzes: { $concatArrays: [ "$quizzes", [ 8, 6 ]  ] } } } ]
)
```

要验证，请查询集合：

```
db.students4.find()
```

## 例5

创建一个示例**temperatures**集合，其中包含摄氏温度(如果该集合当前不存在，则插入操作将创建该集合)：

```
db.temperatures.insertMany([
  { "_id" : 1, "date" : ISODate("2019-06-23"), "tempsC" : [ 4, 12, 17 ] },
  { "_id" : 2, "date" : ISODate("2019-07-07"), "tempsC" : [ 14, 24, 11 ] },
  { "_id" : 3, "date" : ISODate("2019-10-30"), "tempsC" : [ 18, 6, 8 ] }
])
```

要验证，请查询集合：

```
db.temperatures.find()
```

以下[`db.collection.updateMany()`](https://docs.mongodb.com/master/reference/method/db.collection.updateMany/#db.collection.updateMany)操作使用聚合管道以华氏度中的相应温度更新文档：

```
db.temperatures.updateMany( { },
  [
    { $addFields: { "tempsF": {
          $map: {
             input: "$tempsC",
             as: "celsius",
             in: { $add: [ { $multiply: ["$$celsius", 9/5 ] }, 32 ] }
          }
    } } }
  ]
)
```

具体来说，管道由[`$addFields`](https://docs.mongodb.com/master/reference/operator/aggregation/addFields/#pipe._S_addFields)阶段组成，以添加一个新的数组字段**tempsF**，其中包含华氏温度。 要将**tempsC**数组中的每个摄氏温度转换为华氏温度，该阶段将[`$map`](https://docs.mongodb.com/master/reference/operator/aggregation/map/#exp._S_map)表达式与[`$add`](https://docs.mongodb.com/master/reference/operator/aggregation/add/#exp._S_add)和 [`$multiply`](https://docs.mongodb.com/master/reference/operator/aggregation/multiply/#exp._S_multiply)表达式一起使用。

要验证更新，您可以查询集合：

```
db.temperatures.find()
```

## 其他例子

有关其他示例，另请参见各种更新方法页面：

* [db.collection.updateOne](https://docs.mongodb.com/manual/reference/method/db.collection.updateOne/#updateone-example-agg)
* [db.collection.updateMany](https://docs.mongodb.com/manual/reference/method/db.collection.updateMany/#updatemany-example-agg)
* [db.collection.update()](https://docs.mongodb.com/manual/reference/method/db.collection.update/#update-example-agg)
* [db.collection.findOneAndUpdate()](https://docs.mongodb.com/manual/reference/method/db.collection.findOneAndUpdate/#findoneandupdate-agg-pipeline)
* [db.collection.findAndModify()](https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/#findandmodify-agg-pipeline)
* [Bulk.find.update()](https://docs.mongodb.com/manual/reference/method/Bulk.find.update/#example-bulk-find-update-agg)
* [Bulk.find.updateOne()](https://docs.mongodb.com/manual/reference/method/Bulk.find.updateOne/#example-bulk-find-update-one-agg)
* [Bulk.find.upsert()](https://docs.mongodb.com/manual/reference/method/Bulk.find.upsert/#bulk-find-upsert-update-agg-example)

译者：杨帅

校对：杨帅


# 删除文档

此页面使用以下[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell方法

* [db.collection.deleteMany()](https://docs.mongodb.com/manual/reference/method/db.collection.deleteMany/#db.collection.deleteMany)
* [db.collection.deleteOne()](https://docs.mongodb.com/manual/reference/method/db.collection.deleteOne/#db.collection.deleteOne)

此页面上的示例使用**inventory**收集。 要填充**inventory**收集，请运行以下命令：

```
db.inventory.insertMany( [
   { item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
   { item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in" }, status: "P" },
   { item: "paper", qty: 100, size: { h: 8.5, w: 11, uom: "in" }, status: "D" },
   { item: "planner", qty: 75, size: { h: 22.85, w: 30, uom: "cm" }, status: "D" },
   { item: "postcard", qty: 45, size: { h: 10, w: 15.25, uom: "cm" }, status: "A" },
] );
```

## 删除所有文档

要删除集合中的所有文档，请将空的[filter](https://docs.mongodb.com/master/core/document/#document-query-filter)文档{}传递给[`db.collection.deleteMany()`](https://docs.mongodb.com/master/reference/method/db.collection.deleteMany/#db.collection.deleteMany) 方法。

以下示例从**inventory**收集中删除所有文档：

```
db.inventory.deleteMany({})
```

该方法返回具有操作状态的文档。 有关更多信息和示例，请参见[`deleteMany()`](https://docs.mongodb.com/master/reference/method/db.collection.deleteMany/#db.collection.deleteMany).

## 删除所有符合条件的文档

您可以指定标准或过滤器，以标识要删除的文档。 [filter](https://docs.mongodb.com/master/core/document/#document-query-filter)使用与读取操作相同的语法。

要指定相等条件，请在[查询过滤器文档](https://docs.mongodb.com/master/core/document/#document-query-filter):中使用\*\*<`field`>**：**<`value`>\*\*表达式：

```
{ <field1>: <value1>, ... }
```

[查询过滤器文档](https://docs.mongodb.com/master/core/document/#document-query-filter)可以使用[查询操作符](https://docs.mongodb.com/master/reference/operator/query/#query-selectors) 以以下形式指定条件:

```
{ <field1>: { <operator1>: <value1> }, ... }
```

要删除所有符合删除条件的文档，请将[filter](https://docs.mongodb.com/master/core/document/#document-query-filter)参数传递给[`deleteMany()`](https://docs.mongodb.com/master/reference/method/db.collection.deleteMany/#db.collection.deleteMany)方法。

以下示例从状态字段等于\*\*“ A”**的**inventory\*\*集合中删除所有文档：

```
db.inventory.deleteMany({ status : "A" })
```

该方法返回具有操作状态的文档。 有关更多信息和示例，请参见[`deleteMany()`](https://docs.mongodb.com/master/reference/method/db.collection.deleteMany/#db.collection.deleteMany).

## 仅删除一个符合条件的文档

要删除最多一个与指定过滤器匹配的文档(即使多个文档可以与指定过滤器匹配)，请使用[`db.collection.deleteOne()`](https://docs.mongodb.com/master/reference/method/db.collection.deleteOne/#db.collection.deleteOne)方法。

下面的示例删除状态为\*\*“ D”\*\*的第一个文档：

```
db.inventory.deleteOne( { status: "D" } )
```

## 删除行为

### 索引

即使从集合中删除所有文档，删除操作也不会删除索引。

### 原子性

MongoDB中的所有写操作都是单个文档级别的原子操作。 有关MongoDB和原子性的更多信息，请参见[原子性和事务](https://docs.mongodb.com/manual/core/write-operations-atomicity/)。

### 写确认

对于写入问题，您可以指定从MongoDB请求的写入操作的确认级别。 有关详细信息，请参见 [写关注](https://docs.mongodb.com/manual/reference/write-concern/)。

另请参考：

* [db.collection.deleteMany()](https://docs.mongodb.com/manual/reference/method/db.collection.deleteMany/#db.collection.deleteMany)
* [db.collection.deleteOne()](https://docs.mongodb.com/manual/reference/method/db.collection.deleteOne/#db.collection.deleteOne)
* [Additional Methods](https://docs.mongodb.com/manual/reference/delete-methods/#additional-deletes)

译者：杨帅

校对：杨帅


# 删除方法

MongoDB提供以下删除集合文档的方法：

|                                                                                                                                   |                                                  |
| --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ |
| [db.collection.deleteOne()](https://docs.mongodb.com/manual/reference/method/db.collection.deleteOne/#db.collection.deleteOne)    | 即使多个文档可能与指定过滤器匹配，也最多删除一个与指定过滤器匹配的文档。 *3.2版中的新功能* |
| [db.collection.deleteMany()](https://docs.mongodb.com/manual/reference/method/db.collection.deleteMany/#db.collection.deleteMany) | 删除所有与指定过滤器匹配的文档。 *3.2版中的新功能*                     |
| [db.collection.remove()](https://docs.mongodb.com/manual/reference/method/db.collection.remove/#db.collection.remove)             | 删除单个文档或与指定过滤器匹配的所有文档。                            |

## 附加方法

以下方法也可以从集合中删除文档:

* [`db.collection.findOneAndDelete()`](https://docs.mongodb.com/manual/reference/method/db.collection.findOneAndDelete/#db.collection.findOneAndDelete). [`findOneAndDelete()`](https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/#findandmodify-wrapper-sorted-remove)提供排序选项。该选项允许删除按指定 order 排序的第一个文档。
* [`db.collection.findAndModify()`](https://docs.mongodb.com/master/reference/method/db.collection.findAndModify/#db.collection.findAndModify).

  [`db.collection.findAndModify()`](https://docs.mongodb.com/master/reference/method/db.collection.findAndModify/#db.collection.findAndModify) 提供了一个排序选项。 该选项允许删除按指定顺序排序的第一个文档.
* [`db.collection.bulkWrite()`](https://docs.mongodb.com/master/reference/method/db.collection.bulkWrite/#db.collection.bulkWrite).

有关更多方法和示例，请参见各个方法的参考页。

译者：杨帅

校对：杨帅


# 地理空间查询

**在本页面：**

* [地理空间数据](#data)
* [地理空间索引](#indexes)
* [地理空间查询](#queries)
* [地理空间模型](#models)
* [例子](#example)

  MongoDB支持对地理空间数据的查询操作。 本节介绍MongoDB的地理空间功能。

## **地理空间数据**

在MongoDB中，您可以将地理空间数据存储为[GeoJSON](https://docs.mongodb.com/master/geospatial-queries/#geospatial-geojson) 对象或遗留坐标对。

### GeoJSON对象

要计算类地球体的几何形状，请将位置数据存储为[GeoJSON 对象](https://docs.mongodb.com/master/reference/geojson/)。

要指定**GeoJSON**数据，请使用嵌入的文档:

* 一个名为**type**的字段，用于指定**GeoJSON**对象类型
* 一个名为坐标的字段，用于指定对象的坐标。

如果指定纬度和经度坐标，请先列出经度，然后再列出纬度：

* 有效的经度值在\*\*-180**到**180\*\*之间（包括两者）。
* 有效的纬度值在\*\*-90**到**90\*\*之间（包括两者之间）。

```
 <field>: { type: <GeoJSON type> , coordinates: <coordinates> }
```

例如，要指定[GeoJSON Point](https://docs.mongodb.com/master/reference/geojson/#geojson-point):：

```
  location: {
          type: "Point",  
          coordinates: [-73.856077, 40.848447]
    }
```

有关MongoDB支持的**GeoJSON**对象的列表以及示例，请参阅[GeoJSON 对象](https://docs.mongodb.com/master/reference/geojson/)。

对**GeoJSON**对象的MongoDB地理空间查询是在球体上计算的； MongoDB使用[WGS84](https://docs.mongodb.com/master/reference/glossary/#term-wgs84)参考系统对**GeoJSON**对象进行地理空间查询。

### 旧版坐标对

在欧几里德平面上计算距离，请将您的位置数据存储为旧坐标对并使用[`2d`](https://docs.mongodb.com/master/geospatial-queries/#geo-2d)索引。 通过将数据转换为GeoJSON Point类型，MongoDB支持通过[`2dsphere`](https://docs.mongodb.com/master/geospatial-queries/#geo-2dsphere)索引对旧坐标对进行球面计算。

要将数据指定为旧版坐标对，可以使用数组(首选)或嵌入式文档。

#### 通过数组指定(首选)：

```
  <field>: [ <x>, <y> ]
```

如果指定纬度和经度坐标，请先列出经度，然后再列出纬度； 即：

```
  <field>: [<longitude>, <latitude> ]
```

* 有效的经度值在\*\*\[-180 180]\*\*。
* 有效的纬度值在\*\*\[-90 90]\*\*。

#### 通过嵌入式文档指定：

```
  <field>: { <field1>: <x>, <field2>: <y> }
```

如果指定纬度和经度坐标，第一个字段必须包含经度值，而第二个字段必须包含纬度值;即。

```
  <field>: { <field1>: <longitude>, <field2>: <latitude> }
```

* 有效的经度值在\*\*\[-180 180]\*\*。
* 有效的纬度值在\*\*\[-90 90]\*\*。

为了指定旧版坐标对，数组比嵌入式文档更可取，因为某些语言不能保证关联地图的排序。

## 地理空间索引

MongoDB提供以下地理空间索引类型以支持地理空间查询。

**2dsphere**

索引支持查询，该查询可在类似地球的球体上计算几何形状。

要创建**2dsphere**索引，请使用[`db.collection.createIndex()`](https://docs.mongodb.com/manual/reference/method/db.collection.createIndex/#db.collection.createIndex)方法并指定字符串文字“ **2dsphere**”作为索引类型：

```
 db.collection.createIndex( { <location field> : "2dsphere" } )
```

其中\*\*<`location field`>\*\*是其值为GeoJSON对象或旧版坐标对的字段。

有关**2dsphere**索引的更多信息，请参见[`2dsphere`](https://docs.mongodb.com/manual/core/2dsphere/)索引。

**2d**

索引支持在[二维平面上计算几何的查询](https://docs.mongodb.com/master/geospatial-queries/#geospatial-geometry).尽管索引可以支持在球上进行计算的[`$nearSphere`](https://docs.mongodb.com/manual/reference/operator/query/nearSphere/#op._S_nearSphere)查询，但如果可能，请对球面查询使用[2dsphere](https://docs.mongodb.com/master/geospatial-queries/#geo-2dsphere)索引。

要创建**2d**索引，请使用[`db.collection.createIndex()`](https://docs.mongodb.com/manual/reference/method/db.collection.createIndex/#db.collection.createIndex)方法，将location字段指定为键，并将字符串文字\*\*“ 2d”\*\*指定为索引类型：

```
db.collection.createIndex( { <location field> : "2d" } )
```

其中\*\*<`location field`>\*\*是一个值为[旧版坐标对](https://docs.mongodb.com/master/geospatial-queries/#geospatial-legacy)的字段。

有关**2d**索引的更多信息，请参见[2d 索引](https://docs.mongodb.com/manual/core/2d/)。

**地理空间索引和分片集合**

分片集合时，不能将地理空间索引用作分片键。但是，可以通过使用不同的字段作为分片键在分片集合上创建地理空间索引。

分片集合支持以下地理空间操作：

* [$geoNear](https://docs.mongodb.com/manual/reference/operator/aggregation/geoNear/#pipe._S_geoNear)聚集阶段
* [$near](https://docs.mongodb.com/manual/reference/operator/query/near/#op._S_near)和[$nearSphere](https://docs.mongodb.com/manual/reference/operator/query/nearSphere/#op._S_nearSphere)查询运算符(从MongoDB 4.0开始).

从MongoDB 4.0开始，分片集合支持[`$near`](https://docs.mongodb.com/master/reference/operator/query/near/#op._S_near) 和 [`$nearSphere`](https://docs.mongodb.com/master/reference/operator/query/nearSphere/#op._S_nearSphere)查询。

在早期的MongoDB版本中，分片集合不支持[`$near`](https://docs.mongodb.com/master/reference/operator/query/near/#op._S_near) 和 [`$nearSphere`](https://docs.mongodb.com/master/reference/operator/query/nearSphere/#op._S_nearSphere) 查询。相反，对于分片群集，必须使用[`$geoNear`](https://docs.mongodb.com/master/reference/operator/aggregation/geoNear/#pipe._S_geoNear)聚合阶段或**geoNear**命令（在MongoDB 4.0及更低版本中可用）。

您还可以使用[`$geoWithin`](https://docs.mongodb.com/master/reference/operator/query/geoWithin/#op._S_geoWithin)和\*\*$geoIntersect\*\*查询分片群集的地理空间数据。

**涵盖查询**

[地理空间索引](https://docs.mongodb.com/master/geospatial-queries/#index-feature-geospatial)不能[覆盖查询](https://docs.mongodb.com/master/core/query-optimization/#covered-queries)。

## 地理空间查询

> **\[success] Note**
>
> 对于球形查询，请使用**2dsphere**索引结果。
>
> 将**2d**索引用于球形查询可能会导致错误的结果，例如将**2d**索引用于环绕两极的球形查询。

### 地理空间查询操作符

MongoDB提供以下地理空间查询操作符：

| 名字                                                                                                            | 说明                                                                                                                                                                                                                                                                                   |
| ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [$geoIntersects](https://docs.mongodb.com/manual/reference/operator/query/geoIntersects/#op._S_geoIntersects) | 选择与[**GeoJSON**](https://docs.mongodb.com/master/reference/glossary/#term-geojson)几何形状相交的几何形状。 [`2dsphere`](https://docs.mongodb.com/master/core/2dsphere/)索引支持[`$geoIntersects`](https://docs.mongodb.com/master/reference/operator/query/geoIntersects/#op._S_geoIntersects).      |
| [$geoWithin](https://docs.mongodb.com/manual/reference/operator/query/geoWithin/#op._S_geoWithin)             | 选择边界[GeoJSON几何](https://docs.mongodb.com/master/reference/geojson/#geospatial-indexes-store-geojson)图形内的几何图形。[`2dsphere`](https://docs.mongodb.com/master/core/2dsphere/)和2d索引支持[`$geoWithin`](https://docs.mongodb.com/master/reference/operator/query/geoWithin/#op._S_geoWithin). |
| [$near](https://docs.mongodb.com/manual/reference/operator/query/near/#op._S_near)                            | 返回球体上某个点附近的地理空间对象。 需要地理空间索引。 [`2dsphere`](https://docs.mongodb.com/master/core/2dsphere/)和[2d](https://docs.mongodb.com/master/core/2d/)索引支持[`$near`](https://docs.mongodb.com/master/reference/operator/query/near/#op._S_near).                                                    |
| [$nearSphere](https://docs.mongodb.com/manual/reference/operator/query/nearSphere/#op._S_nearSphere)          | 返回接近球体上某一点的地理空间对象。需要地理空间索引。[`2dsphere`](https://docs.mongodb.com/master/core/2dsphere/)和[2d](https://docs.mongodb.com/master/core/2d/)索引支持[`$nearSphere`](https://docs.mongodb.com/master/reference/operator/query/nearSphere/#op._S_nearSphere).                                    |

有关更多细节(包括示例)，请参见个别参考页面。

### 地理空间聚集阶段

MongoDB提供以下地理空间聚合管道阶段：

| 步骤                                                                                                  | 说明                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| --------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [$geoNear](https://docs.mongodb.com/manual/reference/operator/aggregation/geoNear/#pipe._S_geoNear) | 根据与地理空间点的接近程度返回有序的文档流。 合并了地理空间数据的[`$match`](https://docs.mongodb.com/master/reference/operator/aggregation/match/#pipe._S_match), [`$sort`](https://docs.mongodb.com/master/reference/operator/aggregation/sort/#pipe._S_sort), 和 [`$limit`](https://docs.mongodb.com/master/reference/operator/aggregation/limit/#pipe._S_limit)功能。 输出文档包括附加距离字段，并且可以包括位置标识符字段。 [`$geoNear`](https://docs.mongodb.com/master/reference/operator/aggregation/geoNear/#pipe._S_geoNear)需要一个[地理空间索引](https://docs.mongodb.com/master/core/geospatial-indexes/)。 |

有关更多详细信息(包括示例)，请参见[$geoNear](https://docs.mongodb.com/manual/reference/operator/aggregation/geoNear/#pipe._S_geoNear)参考页。

## 地理空间模型

MongoDB地理空间查询可以解释平面或球体上的几何。

**2dsphere**索引仅支持球形查询（即解释球形表面几何形状的查询）。

**2d**索引支持平面查询（即解释平面上的几何图形的查询）和某些球形查询。 虽然**2d**索引支持某些球形查询，但是将**2d**索引用于这些球形查询可能会导致错误。 如果可能，请对球形查询使用**2dsphere**索引。

下表列出了每个地理空间操作所使用的地理空间查询运算符，受支持的查询：

| 操作方式                                                                                                                                                                                                                                                                                                          | 球面/平面查询 | 笔记                                                                                                                                                 |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| [$near](https://docs.mongodb.com/manual/reference/operator/query/near/#op._S_near) ([GeoJSON](https://docs.mongodb.com/manual/geospatial-queries/#geospatial-geojson) centroid point in this line and the following line, [2dsphere](https://docs.mongodb.com/manual/geospatial-queries/#geo-2dsphere) index) | 球形      | 另请参见 [$nearSphere](https://docs.mongodb.com/manual/reference/operator/query/nearSphere/#op._S_nearSphere) 运算符，该运算符与GeoJSON和2dsphere索引一起使用时提供相同的功能。 |
| [$near](https://docs.mongodb.com/manual/reference/operator/query/near/#op._S_near) ([legacy coordinates](https://docs.mongodb.com/manual/geospatial-queries/#geospatial-legacy), [2d](https://docs.mongodb.com/manual/geospatial-queries/#geo-2d) index)                                                      | 平面      |                                                                                                                                                    |
| [$nearSphere](https://docs.mongodb.com/manual/reference/operator/query/nearSphere/#op._S_nearSphere) ([GeoJSON](https://docs.mongodb.com/manual/geospatial-queries/#geospatial-geojson) point, [2dsphere](https://docs.mongodb.com/manual/geospatial-queries/#geo-2dsphere) index)                            | 球形      | 提供与使用GeoJSON点和2dsphere索引的$ near操作相同的功能。对于球形查询，最好使用$ nearSphere而不是$ near运算符，后者在名称中显式指定球形查询。                                                         |
| [$nearSphere](https://docs.mongodb.com/manual/reference/operator/query/nearSphere/#op._S_nearSphere) ([legacy coordinates](https://docs.mongodb.com/manual/geospatial-queries/#geospatial-legacy), [2d](https://docs.mongodb.com/manual/geospatial-queries/#geo-2d) index)                                    | 球形      | 请改用[GeoJSON](https://docs.mongodb.com/manual/reference/glossary/#term-geojson) 点。                                                                  |
| [$geoWithin](https://docs.mongodb.com/manual/reference/operator/query/geoWithin/#op._S_geoWithin) : { [$geometry](https://docs.mongodb.com/manual/reference/operator/query/geometry/#op._S_geometry): … }                                                                                                     | 球形      |                                                                                                                                                    |
| [$geoWithin](https://docs.mongodb.com/manual/reference/operator/query/geoWithin/#op._S_geoWithin) : { [$box](https://docs.mongodb.com/manual/reference/operator/query/box/#op._S_box): … }                                                                                                                    | 平面      |                                                                                                                                                    |
| [$geoWithin](https://docs.mongodb.com/manual/reference/operator/query/geoWithin/#op._S_geoWithin) : { [$polygon](https://docs.mongodb.com/manual/reference/operator/query/polygon/#op._S_polygon): … }                                                                                                        | 平面      |                                                                                                                                                    |
| [$geoWithin](https://docs.mongodb.com/manual/reference/operator/query/geoWithin/#op._S_geoWithin) : { [$center](https://docs.mongodb.com/manual/reference/operator/query/center/#op._S_center): … }                                                                                                           | 平面      |                                                                                                                                                    |
| [$geoWithin](https://docs.mongodb.com/manual/reference/operator/query/geoWithin/#op._S_geoWithin) : { [$centerSphere](https://docs.mongodb.com/manual/reference/operator/query/centerSphere/#op._S_centerSphere): … }                                                                                         | 球形      |                                                                                                                                                    |
| [$geoIntersects](https://docs.mongodb.com/manual/reference/operator/query/geoIntersects/#op._S_geoIntersects)                                                                                                                                                                                                 | 球形      |                                                                                                                                                    |
| [$geoNear](https://docs.mongodb.com/manual/reference/operator/aggregation/geoNear/#pipe._S_geoNear) aggregation stage ([2dsphere](https://docs.mongodb.com/manual/geospatial-queries/#geo-2dsphere) index)                                                                                                    | 球形      |                                                                                                                                                    |
| [$geoNear](https://docs.mongodb.com/manual/reference/operator/aggregation/geoNear/#pipe._S_geoNear) aggregation stage ([2d](https://docs.mongodb.com/manual/geospatial-queries/#geo-2d) index)                                                                                                                | 平面      |                                                                                                                                                    |

## 例子

用以下文档创建一个集合**places**:

```
db.places.insert( { 
        name: "Central Park", 
        location: { type: "Point", coordinates: [ -73.97, 40.77 ] },
        category: "Parks"
} );
db.places.insert( {
        name: "Sara D. Roosevelt Park",
        location: { type: "Point", coordinates: [ -73.9928, 40.7193 ] }, 
        category: "Parks"
);
db.places.insert( {
        name: "Polo Grounds",
        location: { type: "Point", coordinates: [ -73.9375, 40.8303 ] },
        category: "Stadiums"} 
);
```

以下操作在**location**字段上创建**2dsphere**索引：

```
db.places.createIndex( { location: "2dsphere" } )
```

以下查询使用[$near](/mongodb-crud-operations/geospatial-queries)运算符返回距指定GeoJSON点至少1000米，最多5000米的文档，并按从最近到最远的顺序排序：

```
db.places.find(  
        {   
            location:  
                { $near:   
                    {  
                        $geometry: { type: "Point",  coordinates: [ -73.9667, 40.78 ] },   
                        $minDistance: 1000,      
                        $maxDistance: 5000    
                    }   
                } 
        }
)
```

以下操作使用**geoNea**r聚合操作返回与查询过滤器\*\*{category：“ Parks”}\*\*匹配的文档，这些文档按从最接近指定GeoJSON点的最近到最远的顺序排序：

```
db.places.aggregate( [
        {     
            $geoNear: { 
                near: { type: "Point", coordinates: [ -73.9667, 40.78 ] }, 
                spherical: **true**,       
                query: { category: "Parks" },  
                distanceField: "calcDistance"  
            } 
        }
])
```

译者：杨帅

校对：杨帅


# 用地理空间查询查找餐馆

**在本页面**

* [总览](#overview)
* [失真](#distortion)
* [搜索餐厅](#searching)

  **总览**

MongoDB的地理空间索引使您可以高效地对包含地理空间形状和点的集合执行空间查询。为了展示地理空间要素的功能并比较不同的方法，本教程将指导您完成为简单地理空间应用程序编写查询的过程。

本教程将简要介绍地理空间索引的概念，然后演示它们在[`$geoWithin`](https://docs.mongodb.com/master/reference/operator/query/geoWithin/#op._S_geoWithin), [`$geoIntersects`](https://docs.mongodb.com/master/reference/operator/query/geoIntersects/#op._S_geoIntersects), 和 [`$nearSphere`](https://docs.mongodb.com/master/reference/operator/query/nearSphere/#op._S_nearSphere).中的用法。

假设您正在设计一个移动应用程序，以帮助用户找到纽约市的餐馆。该应用程序必须：

* 使用[`$geoIntersects`](https://docs.mongodb.com/master/reference/operator/query/geoIntersects/#op._S_geoIntersects)确定用户当前所在的社区
* 使用[`$geoWithin`](https://docs.mongodb.com/master/reference/operator/query/geoWithin/#op._S_geoWithin)显示附近的餐馆数量，
* 使用[`$nearSphere`](https://docs.mongodb.com/master/reference/operator/query/nearSphere/#op._S_nearSphere)在用户指定距离内查找餐馆

本教程将使用**2dsphere**索引来查询有关球形几何的数据。

有关球面和平面几何的更多信息，请参见[Geospatial Models](https://docs.mongodb.com/master/geospatial-queries/#geospatial-geometry).

## 失真

由于将三维球体（例如地球）投影到平面上的性质，当在地图上可视化时，球形几何形状将显得失真。

例如，以经度纬度点`(0,0)`, `(80,0)`, `(80,80)`, and `(0,80)`. 定义的球形正方形的规格为例。下图描述了此区域覆盖的区域：![](https://docs.mongodb.com/manual/_images/geospatial-spherical-square.png)

## 搜索餐厅

### 前提条件

从<https://raw.githubusercontent.com/mongodb/docs-assets/geospatial/neighborhoods.json和https://raw.githubusercontent.com/mongodb/docs-assets/geospatial/restaurants.json下载示例数据集。它们分别包含收藏餐馆和社区。>

下载数据集后，将它们导入数据库：

```
mongoimport <path to restaurants.json> -c=restaurants
mongoimport <path to neighborhoods.json> -c=neighborhoods
```

地理空间索引，几乎总是可以提高[`$geoWithin`](https://docs.mongodb.com/master/reference/operator/query/geoWithin/#op._S_geoWithin) and [`$geoIntersects`](https://docs.mongodb.com/master/reference/operator/query/geoIntersects/#op._S_geoIntersects) 查询的性能。

由于此数据是地理数据，因此请使用[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell在每个集合上创建**2dsphere**索引：

```
db.restaurants.createIndex({ location: "2dsphere" })
db.neighborhoods.createIndex({ geometry: "2dsphere" })
```

### 探索数据

从[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell中检查新创建的餐厅集合中的条目：

```
db.restaurants.findOne()
```

该查询返回如下文档：

```
    { 
            location:   
                    type: "Point", 
                    coordinates: [-73.856077, 40.848447]
            },
            name: "Morris Park Bake Shop"
    }
```

该餐厅文档对应于下图所示的位置：\
![](https://docs.mongodb.com/manual/_images/geospatial-single-point.png)\
由于本教程使用**2dsphere**索引，因此**location**字段中的几何数据必须遵循[GeoJSON 格式](https://docs.mongodb.com/master/reference/geojson/).

现在检查**neighborhoods**集合中的条目：

```
db.neighborhoods.findOne()
```

该查询将返回如下文档：

```
  {
            geometry:  
                type: "Polygon", 
                coordinates: [[
                    [ -73.99, 40.75 ], 
                    ...
                    [ -73.98, 40.76 ], 
                    [ -73.99, 40.75 ] 
                ]]  
            },  
            name: "Hell's Kitchen"
   }
```

该几何形状对应于下图所示的区域：

### ![](https://docs.mongodb.com/manual/_images/geospatial-polygon-hells-kitchen.png) 找到当前的街区

假设用户的移动设备可以为用户提供相当准确的位置，那么使用[`$geoIntersects`](https://docs.mongodb.com/master/reference/operator/query/geoIntersects/#op._S_geoIntersects).很容易找到用户当前的街区。

假设用户位于经度\*\*-73.93414657**和纬度**40.82302903\*\*。 要找到当前邻域，您将使用**GeoJSON**格式的特殊[$geometry](/mongodb-crud-operations/geospatial-queries/find-restaurants-with-geospatial-queries)字段指定一个点：

```
db.neighborhoods.findOne({ geometry: { $geoIntersects: { $geometry: { type: "Point", coordinates: [ -73.93414657, 40.82302903 ] } } } })
```

该查询将返回以下结果：

```
    {
            "_id" : ObjectId("55cb9c666c522cafdb053a68"),
            "geometry" :   
                    "type" : "Polygon",
                    "coordinates" : [
                            [             
                                [          
                                        -73.93383000695911,
                                        40.81949109558767 
                                ],           
                                ...     
                            ]    
                    ] 
            },
            "name" : "Central Harlem North-Polo Grounds"
    }
```

### 查找附近的所有餐厅

您还可以查询以查找给定社区中包含的所有餐馆。 在mongo shell中运行以下命令以查找包含用户的社区，然后计算该社区内的餐馆：

```
var neighborhood = db.neighborhoods.findOne( { geometry: { $geoIntersects: { $geometry: { type: "Point", coordinates: [ -73.93414657, 40.82302903 ] } } } } )
db.restaurants.find( { location: { $geoWithin: { $geometry: neighborhood.geometry } } } ).count()
```

该查询将告诉您，所请求的社区中有127家餐厅，如下图所示：\
![](https://docs.mongodb.com/manual/_images/geospatial-all-restaurants.png)

### 查找附近的餐厅

要查找点指定距离内的餐厅，可以将[`$geoWithin`](https://docs.mongodb.com/master/reference/operator/query/geoWithin/#op._S_geoWithin)与 [`$centerSphere`](https://docs.mongodb.com/master/reference/operator/query/centerSphere/#op._S_centerSphere)一起按未排序的顺序返回结果，或者如果需要按距离对结果进行排序，则可以将**NearSphere**与[`$maxDistance`](https://docs.mongodb.com/master/reference/operator/query/maxDistance/#op._S_maxDistance)一起返回。

#### 未排序$geoWithin

要查找圆形区域内的餐厅，请将[`$geoWithin`](https://docs.mongodb.com/master/reference/operator/query/geoWithin/#op._S_geoWithin)与[`$centerSphere`](https://docs.mongodb.com/master/reference/operator/query/centerSphere/#op._S_centerSphere)一起使用。 [`$centerSphere`](https://docs.mongodb.com/master/reference/operator/query/centerSphere/#op._S_centerSphere).是MongoDB特定的语法，它通过以弧度指定中心和半径来表示圆形区域。

[`$geoWithin`](https://docs.mongodb.com/master/reference/operator/query/geoWithin/#op._S_geoWithin)不会以任何特定顺序返回文档，因此它可能会首先向用户显示最远的文档。

以下内容将查找距用户五英里范围内的所有餐馆：

```
db.restaurants.find({ location:
    { $geoWithin:   
        { $centerSphere: [ [ -73.93414657, 40.82302903 ], 5 / 3963.2 ] } } })
```

’s的第二个参数接受以弧度为单位的半径，因此您必须将其除以以英里为单位的地球半径。 有关在距离单位之间进行转换的更多信息，请参见[使用球面几何计算距离](https://docs.mongodb.com/master/tutorial/calculate-distances-using-spherical-geometry-with-2d-geospatial-indexes/) 。

#### 用$nearSphere排序

您也可以使用[`$nearSphere`](https://docs.mongodb.com/master/reference/operator/query/nearSphere/#op._S_nearSphere) 并以米为单位指定[`$maxDistance`](https://docs.mongodb.com/master/reference/operator/query/maxDistance/#op._S_maxDistance) 项。 这将按照从最近到最远的排序顺序返回用户五英里范围内的所有餐馆：

```
var METERS_PER_MILE = 1609.34
db.restaurants.find({ location: { $nearSphere: { $geometry: { type: "Point", coordinates: [ -73.93414657, 40.82302903 ] }, $maxDistance: 5 * METERS_PER_MILE } } })
```

译者：杨帅

校对：杨帅


# GeoJSON对象

**在本页面**

* [总览](#概观)
* [`Point`](#点)
* [`LineString`](#线串)
* [多边形](#多边形)
* [多点](#多点)
* [MULTILINESTRING](#id1)
* [MultiPolygon](#id2)
* [GeometryCollection](#id3)

## 总览

MongoDB 支持此页面上列出的 GeoJSON object 类型。

要指定 GeoJSON 数据，请使用嵌入式文档：

* 一个名为`type`的字段，用于指定[GeoJSON对象类型](https://docs.mongodb.com/master/reference/geojson/#)
* 一个名为`coordinates`的字段，用于指定 object 的坐标。

如果指定纬度和经度坐标，请首先列出**经度**，然后列出**纬度**：

* 有效的经度值介于\*\*\[-180 180]\*\*。
* 有效纬度值介于\*\*\[-90 90]\*\*。

```
<field>: { type: <GeoJSON type> , coordinates: <coordinates> }
```

GeoJSON objects 上的 MongoDB 地理空间查询在球体上计算; MongoDB 使用[`WGS84`](https://docs.mongodb.com/master/reference/glossary/#term-wgs84)参考系统对 GeoJSON objects 进行地理空间查询。

## `Point`

以下 example 指定了 GeoJSON [点](https://tools.ietf.org/html/rfc7946#section-3.1.2)：

```
{type:"Point",coordinates:[40,5]}
```

## `LineString`

以下 example 指定了GeoJSON[LineString](https://tools.ietf.org/html/rfc7946#section-3.1.4)：

```
{ type: "LineString", coordinates: [ [ 40, 5 ], [ 41, 6 ] ] }
```

## 多边形

多边形由一组 GeoJSON `LinearRing`坐标数组组成。这些`LinearRings`已关闭`LineStrings`。 Closed `LineStrings`至少有四个坐标对，并指定与第一个和最后一个坐标相同的位置。

连接曲面上两个点的 line 可能包含也可能不包含在平面上连接这两个点的同一组 co-ordinates。连接曲面上两点的 line 将是一个测地线。仔细检查点以避免共享边缘的错误，以及重叠和其他类型的交叉点。

### 单环多边形

以下 example 指定具有外环并且没有内环(或孔)的 GeoJSON `Polygon`。第一个和最后一个坐标必须 order 在 order 中才能关闭多边形：

```
{
  type: "Polygon",
  coordinates: [ [ [ 0 , 0 ] , [ 3 , 6 ] , [ 6 , 1 ] , [ 0 , 0  ] ] ]
}
```

对于具有单个环的多边形，环不能 self-intersect。

### 具有多个环的多边形

对于具有多个环的多边形：

* 第一个描述的环必须是外环。
* 外圈不能 self-intersect。
* 任何内圈必须完全由外圈包含。
* 内圈不能相互交叉或重叠。内圈不能共享边缘。

以下 example 表示具有内部环的 GeoJSON 多边形：

```
{
    type : "Polygon",
    coordinates : [
    [ [ 0 , 0 ] , [ 3 , 6 ] , [ 6 , 1 ] , [ 0 , 0 ] ],
    [ [ 2 , 2 ] , [ 3 , 3 ] , [ 4 , 2 ] , [ 2 , 2 ] ]
    ]
  }
```

![Diagram of a Polygon with internal ring.](https://docs.mongodb.com/master/_images/index-2dsphere-polygon-with-ring.bakedsvg.svg)

## 多点

需要的[版本](https://docs.mongodb.com/master/core/2dsphere/#dsphere-v2)

GeoJSON[MultiPoint](https://tools.ietf.org/html/rfc7946#section-3.1.3)嵌入式文档编码点列表。

```
{
    type: "MultiPoint",
    coordinates: [
       [ -73.9580, 40.8003 ],
       [ -73.9498, 40.7968 ],
       [ -73.9737, 40.7648 ],
       [ -73.9814, 40.7681 ]
  ]
    }
```

## `MultiLineString`

需要的[版本](https://docs.mongodb.com/master/core/2dsphere/#dsphere-v2)

以下 example 指定了 GeoJSON [MultiLineString](https://tools.ietf.org/html/rfc7946#section-3.1.5):

```
 {
  type: "MultiLineString",
      coordinates: [
         [ [ -73.96943, 40.78519 ], [ -73.96082, 40.78095 ] ],
         [ [ -73.96415, 40.79229 ], [ -73.95544, 40.78854 ] ],
         [ [ -73.97162, 40.78205 ], [ -73.96374, 40.77715 ] ],
         [ [ -73.97880, 40.77247 ], [ -73.97036, 40.76811 ] ]
           ]
      }
```

## `MultiPolygon`

需要的[版本](https://docs.mongodb.com/master/core/2dsphere/#dsphere-v2)

以下 example 指定了GeoJSON[MultiPolygon](https://tools.ietf.org/html/rfc7946#section-3.1.7):

```
{
  type: "MultiPolygon",
      coordinates: [
         [ [ [ -73.958, 40.8003 ], [ -73.9498, 40.7968 ], [ -73.9737, 40.7648 ], [ -73.9814, 40.7681 ], [ -73.958, 40.8003 ] ] ],
         [ [ [ -73.958, 40.8003 ], [ -73.9498, 40.7968 ], [ -73.9737, 40.7648 ], [ -73.958, 40.8003 ] ] ]
      ]
    }
```

## `GeometryCollection`

需要的[版本](https://docs.mongodb.com/master/core/2dsphere/#dsphere-v2)

以下 example store GeoJSON类型 [GeometryCollection](https://tools.ietf.org/html/rfc7946#section-3.1.8)的坐标:

```
{
    type: "GeometryCollection",
      geometries: [
         {
           type: "MultiPoint",
           coordinates: [
              [ -73.9580, 40.8003 ],
              [ -73.9498, 40.7968 ],
              [ -73.9737, 40.7648 ],
              [ -73.9814, 40.7681 ]
           ]
         },
         {
           type: "MultiLineString",
           coordinates: [
              [ [ -73.96943, 40.78519 ], [ -73.96082, 40.78095 ] ],
              [ [ -73.96415, 40.79229 ], [ -73.95544, 40.78854 ] ],
              [ [ -73.97162, 40.78205 ], [ -73.96374, 40.77715 ] ],
              [ [ -73.97880, 40.77247 ], [ -73.97036, 40.76811 ] ]
           ]
        }
    ]
  }
```

​

译者：杨帅

校对：杨帅


# 批量写入操作

> **在本页面**
>
> * [总览](https://docs.mongodb.com/manual/core/bulk-write-operations/#overview)
> * [有序 VS 无序操作](https://docs.mongodb.com/manual/core/bulk-write-operations/#ordered-vs-unordered-operations)
> * [bulkWrite()方法](https://docs.mongodb.com/manual/core/bulk-write-operations/#bulkwrite-methods)
> * [批量插入分片集合的策略](https://docs.mongodb.com/manual/core/bulk-write-operations/#strategies-for-bulk-inserts-to-a-sharded-collection)

## 总览

MongoDB使客户端能够批量执行写操作。 批量写入操作会影响单个集合。 MongoDB允许应用程序确定批量写入操作所需的可接受的确认级别。

*3.2版本新增*

[`db.collection.bulkWrite()`](https://docs.mongodb.com/master/reference/method/db.collection.bulkWrite/#db.collection.bulkWrite)方法提供了执行批量插入，更新和删除操作的能力。对于批量插入而言，MongoDB也支持[`db.collection.insertMany()`](https://docs.mongodb.com/master/reference/method/db.collection.insertMany/#db.collection.insertMany).

## 有序 VS 无序操作

批量写操作可以是有序的，也可以无序的。

使用操作的有序列表，MongoDB串行地执行操作。 如果在某个单独的写操作的处理过程中发生错误，MongoDB将直接返回而不再继续处理列表中任何剩余的写操作。 请参考[有序的批量写入](https://docs.mongodb.com/manual/reference/method/db.collection.bulkWrite/#bulkwrite-example-bulk-write-operation).

使用无序的操作列表，MongoDB可以并行地执行操作，但是不能保证此行为。 如果某个单独的写操作的处理过程中发生错误，MongoDB将继续处理列表中剩余的写操作。 请参考[无序的批量写入](https://docs.mongodb.com/manual/reference/method/db.collection.bulkWrite/#bulkwrite-example-unordered-bulk-write)。

在分片集合上执行有序的批量写操作通常比执行无序批量写操作要慢。这是因为对于有序列表而言，每个操作都必须等待上一个操作完成后才能执行。

默认情况下，[`bulkWrite()`](https://docs.mongodb.com/master/reference/method/db.collection.bulkWrite/#db.collection.bulkWrite) 执行**有序的**写入。 要指定**无序的**写入，请在选项文档中设置**ordered：false**。

请参考[操作的执行](https://docs.mongodb.com/manual/reference/method/db.collection.bulkWrite/#bulkwrite-write-operations-executionofoperations).

## bulkWrite()方法

[`bulkWrite()`](https://docs.mongodb.com/manual/reference/method/db.collection.bulkWrite/#db.collection.bulkWrite)支持如下操作：

* [insertOne](https://docs.mongodb.com/manual/reference/method/db.collection.bulkWrite/#bulkwrite-write-operations-insertone)
* [updateOne](https://docs.mongodb.com/manual/reference/method/db.collection.bulkWrite/#bulkwrite-write-operations-updateonemany)
* [updateMany](https://docs.mongodb.com/manual/reference/method/db.collection.bulkWrite/#bulkwrite-write-operations-updateonemany)
* [replaceOne](https://docs.mongodb.com/manual/reference/method/db.collection.bulkWrite/#bulkwrite-write-operations-replaceone)
* [deleteOne](https://docs.mongodb.com/manual/reference/method/db.collection.bulkWrite/#bulkwrite-write-operations-deleteonemany)
* [deleteMany](https://docs.mongodb.com/manual/reference/method/db.collection.bulkWrite/#bulkwrite-write-operations-deleteonemany)

每个写操作都以数组中的文档形式被传递给\[[`bulkWrite()`](https://docs.mongodb.com/master/reference/method/db.collection.bulkWrite/#db.collection.bulkWrite)

例如，下面执行多个写操作:

**characters**集合包含以下文档:

```
{ "_id" : 1, "char" : "Brisbane", "class" : "monk", "lvl" : 4 },
{ "_id" : 2, "char" : "Eldon", "class" : "alchemist", "lvl" : 3 },
{ "_id" : 3, "char" : "Meldane", "class" : "ranger", "lvl" : 3 }
```

接下来的[`bulkWrite()`](https://docs.mongodb.com/master/reference/method/db.collection.bulkWrite/#db.collection.bulkWrite)将在此集合上执行批量写入的操作。

```
try {
   db.characters.bulkWrite(
      [
         { insertOne :
            {
               "document" :
               {
                  "_id" : 4, "char" : "Dithras", "class" : "barbarian", "lvl" : 4
               }
            }
         },
         { insertOne :
            {
               "document" :
               {
                  "_id" : 5, "char" : "Taeln", "class" : "fighter", "lvl" : 3
               }
            }
         },
         { updateOne :
            {
               "filter" : { "char" : "Eldon" },
               "update" : { $set : { "status" : "Critical Injury" } }
            }
         },
         { deleteOne :
            { "filter" : { "char" : "Brisbane"} }
         },
         { replaceOne :
            {
               "filter" : { "char" : "Meldane" },
               "replacement" : { "char" : "Tanys", "class" : "oracle", "lvl" : 4 }
            }
         }
      ]
   );
}
catch (e) {
   print(e);
}
```

该操作将返回如下的结果：

```
{
   "acknowledged" : true,
   "deletedCount" : 1,
   "insertedCount" : 2,
   "matchedCount" : 2,
   "upsertedCount" : 0,
   "insertedIds" : {
      "0" : 4,
      "1" : 5
   },
   "upsertedIds" : {

   }
}
```

想了解更多例子，请参考[`bulkWrite() 示例`](https://docs.mongodb.com/manual/reference/method/db.collection.bulkWrite/#bulkwrite-example-bulk-write-operation).

## 批量插入分片集合的策略

大容量插入操作(包括初始数据插入或例程数据导入)可能会影响分片集群的性能。对于批量插入，考虑以下策略:

### 对分片集合进行预拆分

如果分片集合为空，则该集合只有一个存储在单个分片上的初始数据块，MongoDB必须花一些时间来接收数据，创建拆分并将拆分的块分发到其他分片上。为了避免这种性能开销，您可以对分片集合进行预拆分，请参考 [分片集群中的数据块拆分](https://docs.mongodb.com/master/tutorial/split-chunks-in-sharded-cluster/)中的描述。

### 对mongos的无序写入

要提高对分片集群的写入性能，请使用带有可选参数`ordered:false`的[`bulkWrite()`](https://docs.mongodb.com/master/reference/method/db.collection.bulkWrite/#db.collection.bulkWrite)方法。[`mongos`](https://docs.mongodb.com/master/reference/program/mongos/#bin.mongos) 会尝试同时将写入发送到多个分片。对于空集合，请首先按照[分片集群中的数据块拆分](https://docs.mongodb.com/master/tutorial/split-chunks-in-sharded-cluster/)中描述的进行集合的预拆分。

### 避免单调插入带来的瓶颈

如果您的分片键再插入过程中时单调增加的，那么所有插入的数据都会插入到该分片集合的最后一个数据块中，也就是说会落到某单个分片上。因此，集群的插入能力将永远不会超过该单个跟片的插入性能（木桶的短板原理）。

如果插入量大于单个分片可以处理的数据量，并且无法避免单调增加的分片键，那么可以考虑对应用程序进行如下修改：

* 翻转分片键的二进制位。这样可以保留信息的同时避免插入顺序与递增插入值之间的关联性。
* 交换第一个和最后16比特来实现“随机”插入。

**示例**

下面的C++例子中，交换生成的[`BSON`](https://docs.mongodb.com/master/reference/glossary/#term-bson) [`ObjectIds`](https://docs.mongodb.com/master/reference/glossary/#term-objectid)的前导和后16位字，使它们不再单调递增。

```
using namespace mongo;
OID make_an_id() {
  OID x = OID::gen();
  const unsigned char *p = x.getData();
  swap( (unsigned short&) p[0], (unsigned short&) p[10] );
  return x;
}

void foo() {
  // create an object
  BSONObj o = BSON( "_id" << make_an_id() << "x" << 3 << "name" << "jane" );
  // now we may insert o into a sharded collection
}
```

另请参考

[分片键](https://docs.mongodb.com/manual/core/sharding-shard-key/#sharding-internals-shard-keys)来获得如何选择分片键的相关信息。另请参考【分片键】（尤其是其中【[选择分片键](https://docs.mongodb.com/manual/core/sharding-shard-key/#sharding-internals-operations-and-reliability)】的相关章节）

关于选择[分片键](https://docs.mongodb.com/manual/core/sharding-shard-key/#sharding-internals-shard-keys)的信息。还请参阅[分片键内部](https://docs.mongodb.com/master/core/sharding-shard-key/#sharding-internals-shard-keys)(特别是，[选择一个切分键](https://docs.mongodb.com/master/core/sharding-shard-key/#sharding-internals-operations-and-reliability))。

译者：杨帅 刘翔

校验：杨帅


# 可重试写入

**在本页面**

* [前提条件](#prerequisites)
* [可重试写入和多文档交易](#transactions)
* [启用可重试写入](#enabling)
* [可重试的写操作](#write)
* [行为](#behavior)

*3.6版的新功能*

可重试写入允许MongoDB驱动程序在遇到网络错误或在复制集或分片群集中找不到正常的主操作时自动重试特定的写操作一次。

## 前提条件

可重试写入具有以下要求：

### 支持的部署Topologie

​ 可重试写入需要 [复制集](https://docs.mongodb.com/master/replication/#replication)或[分片群集](https://docs.mongodb.com/master/sharding/#sharding-introduction)，并且不支持独立实例。

### 支持的存储引擎

​ 可重试写入需要支持文档级锁定的存储引擎，例如[WiredTiger](https://docs.mongodb.com/master/core/wiredtiger/)或[内存中](https://docs.mongodb.com/master/core/inmemory/) 存储引擎。

### 3.6+ MongoDB驱动程序

客户端需要为MongoDB 3.6或更高版本更新的MongoDB驱动程序：

| Java 3.6+ Python 3.6+ C 1.9+ | C# 2.5+ Node 3.0+ Ruby 2.5+ | Perl 2.0+ PHPC 1.4+ Scala 2.2+ |
| ---------------------------- | --------------------------- | ------------------------------ |
|                              |                             |                                |

### MongoDB版本

集群中每个节点的MongoDB版本必须为**3.6**或更高，集群中每个节点的**featureCompatibilityVersion**必须为**3.6**或更高。有关**featureCompatibilityVersion**标志的更多信息，请参见[setFeatureCompatibilityVersion](https://docs.mongodb.com/manual/reference/command/setFeatureCompatibilityVersion/#dbcmd.setFeatureCompatibilityVersion)。

### 写确认书

[`Write Concern`](https://docs.mongodb.com/master/reference/write-concern/)为**0**的写操作是不可重试的。

## 可重试写入和多文档交易

*版本4.0中的新功能*

[事务提交和中止操作](https://docs.mongodb.com/master/core/transactions-in-applications/#transactions-retry)是可重试的写操作。如果提交操作或中止操作遇到错误，MongoDB驱动程序将重试操作一次，而不管[`retryWrites`](https://docs.mongodb.com/master/reference/connection-string/#urioption.retryWrites)是否被设置为**false**。

有关交易的更多信息，请参见[Transactions](https://docs.mongodb.com/master/core/transactions/)。

## 启用可重试写入

### MongoDB驱动程序

官方的MongoDB 3.6和4.0兼容驱动程序需要在连接字符串中包含[`retryWrites=true`](https://docs.mongodb.com/master/reference/connection-string/#urioption.retryWrites)选项，以启用该连接的可重试写操作。

官方的MongoDB 4.2兼容驱动程序在默认情况下启用了可重试写。升级到与4.2兼容的驱动程序，要求可重试写的应用程序可能会忽略[`retryWrites=true`](https://docs.mongodb.com/master/reference/connection-string/#urioption.retryWrites)选项。升级到与4.2兼容的驱动程序，要求禁用可重试写的应用程序必须在连接字符串中包含[`retryWrites=false`](https://docs.mongodb.com/master/reference/connection-string/#urioption.retryWrites)。

**Mongo shell**

要在mongo shell中启用可重试写入，请使用[`--retryWrites`](https://docs.mongodb.com/master/reference/program/mongo/#cmdoption-mongo-retrywrites)命令行选项：

```
mongo --retryWrites
```

## 可重试的写操作

当发出已确认的写关注时，可以重试以下写操作; 例如,[`Write Concern`](https://docs.mongodb.com/manual/reference/write-concern/)不能为\*\*{w：0}\*\*。

> **\[success] Note**
>
> 事务中的写操作不能单独重试。

| 方法                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        | 说明                                                                                            |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
| [db.collection.insertOne()](https://docs.mongodb.com/manual/reference/method/db.collection.insertOne/#db.collection.insertOne) [db.collection.insert()](https://docs.mongodb.com/manual/reference/method/db.collection.insert/#db.collection.insert) [db.collection.insertMany()](https://docs.mongodb.com/manual/reference/method/db.collection.insertMany/#db.collection.insertMany)                                                                                                                                                                                                                                                                                    | 插入操作                                                                                          |
| [db.collection.updateOne()](https://docs.mongodb.com/manual/reference/method/db.collection.updateOne/#db.collection.updateOne) [db.collection.replaceOne()](https://docs.mongodb.com/manual/reference/method/db.collection.replaceOne/#db.collection.replaceOne) [db.collection.save()](https://docs.mongodb.com/manual/reference/method/db.collection.save/#db.collection.save) [db.collection.update()](https://docs.mongodb.com/manual/reference/method/db.collection.update/#db.collection.update) where `multi` is `false`                                                                                                                                           | 单文档更新操作。                                                                                      |
| [db.collection.deleteOne()](https://docs.mongodb.com/manual/reference/method/db.collection.deleteOne/#db.collection.deleteOne) [db.collection.remove()](https://docs.mongodb.com/manual/reference/method/db.collection.remove/#db.collection.remove) where justOne is true                                                                                                                                                                                                                                                                                                                                                                                                | 单个文档删除操作                                                                                      |
| [db.collection.findAndModify()](https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/#db.collection.findAndModify) [db.collection.findOneAndDelete()](https://docs.mongodb.com/manual/reference/method/db.collection.findOneAndDelete/#db.collection.findOneAndDelete) [db.collection.findOneAndReplace()](https://docs.mongodb.com/manual/reference/method/db.collection.findOneAndReplace/#db.collection.findOneAndReplace) [db.collection.findOneAndUpdate()](https://docs.mongodb.com/manual/reference/method/db.collection.findOneAndUpdate/#db.collection.findOneAndUpdate)                                                                 | **findAndModify**操作。所有**findAndModify**操作都是单个文档操作。                                            |
| [db.collection.bulkWrite()](https://docs.mongodb.com/manual/reference/method/db.collection.bulkWrite/#db.collection.bulkWrite) 具有以下写操作： . [insertOne](https://docs.mongodb.com/manual/reference/method/db.collection.bulkWrite/#bulkwrite-write-operations-insertone) . [updateOne](https://docs.mongodb.com/manual/reference/method/db.collection.bulkWrite/#bulkwrite-write-operations-updateonemany) . [replaceOne](https://docs.mongodb.com/manual/reference/method/db.collection.bulkWrite/#bulkwrite-write-operations-replaceone) . [deleteOne](https://docs.mongodb.com/manual/reference/method/db.collection.bulkWrite/#bulkwrite-write-operations-deleteonemany) | 只包含单文档写操作的批量写操作。可重试的大容量操作可以包括指定的写操作的任何组合，但不能包括任何多文档写操作，比如**updateMany**。                      |
| [Bulk](https://docs.mongodb.com/manual/reference/method/Bulk/#Bulk) operations for: . [Bulk.find.removeOne()](https://docs.mongodb.com/manual/reference/method/Bulk.find.removeOne/#Bulk.find.removeOne) . [Bulk.find.replaceOne()](https://docs.mongodb.com/manual/reference/method/Bulk.find.replaceOne/#Bulk.find.replaceOne) . [Bulk.find.replaceOne()](https://docs.mongodb.com/manual/reference/method/Bulk.find.replaceOne/#Bulk.find.replaceOne)                                                                                                                                                                                                                  | 仅由单文档写操作组成的批量写操作。可重试的大容量操作可以包括指定的写操作的任何组合，但不能包括任何多文档写操作，比如**update**，它为**multi**选项指定**true**。 |

> **分片键值更新**
>
> 从MongoDB 4.2开始，您可以通过发布可重试写入或事务处理中的单文档**update / findAndModify**操作来更新文档的分片键值(除非分片键字段是不可变的\*\*\_id\*\*字段)。 有关详细信息，请参见[更改文档的分片键值](https://docs.mongodb.com/master/core/sharding-shard-key/#update-shard-key).。

* MongoDB 4.2将重试遇到重复密钥异常的某些单文档upsert（更新使用**upsert：true**和**multi：false**）。 有关条件，请参阅 [Duplicate Key Errors on Upsert](https://docs.mongodb.com/master/core/retryable-writes/#retryable-update-upsert) .
* 在MongoDB 4.2之前，MongoDB不会重试遇到重复键错误的upsert操作。

## 行为

### 持续的网络错误

MongoDB可重试写只做一次重试尝试。这有助于解决暂时的网络错误和复制集选举，但不能解决持久的网络错误。

### 故障转移期

如果驱动程序在目标复制集中或分片集群分片中找不到正常的主服务器，则驱动程序在重试之前会等待[`serverSelectionTimeoutMS`](https://docs.mongodb.com/manual/reference/connection-string/#urioption.serverSelectionTimeoutMS)毫秒来确定新的主服务器。可重试写操作不会处理故障转移周期超过[`serverSelectionTimeoutMS`](https://docs.mongodb.com/manual/reference/connection-string/#urioption.serverSelectionTimeoutMS)的实例。

> **\[warning] Warning**
>
> 如果客户端应用程序在发出写操作后的时间超过[`localLogicalSessionTimeoutMinutes`](https://docs.mongodb.com/master/reference/parameters/#param.localLogicalSessionTimeoutMinutes)，那么当客户端应用程序开始响应时(无需重新启动)，可能会重试并再次应用写操作。

### Upsert上的重复键错误

MongoDB 4.2将重试单文档的upsert操作(即:**upsert: true**和**multi: false**)由于重复的键错误而失败，只有当操作满足以下所有条件:

* 目标集合具有导致重复键错误的唯一索引。
* 更新匹配条件为：
  * 单个相等谓词

    **{ "fieldA" : "valueA" }**，
  * 相等谓词的逻辑

    **{ "fieldA" : "valueA", "fieldB" : "valueB" }**
* 唯一索引键模式中的字段集与更新查询谓词中的字段集匹配。
* 更新操作不会修改查询谓词中的任何字段。

  下表包含服务器可以或不能在重复键错误时重试的upsert操作示例：

|                                 |                                                                                                                                     |                                                           |
| ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- |
| **唯一索引键模式**                     | **更新操作**                                                                                                                            | **可重试**                                                   |
| { \_id ： **1** }                | db.collName.updateOne( { \_id : ObjectId("**1aa1c1efb123f14aaa167aaa**") }, { $set : { fieldA : **25** } }, { upsert : **true** } ) | 是                                                         |
| { fieldA ： **1** }              | db.collName.updateOne( { fieldA : { $in : \[ **25** ] } }, { $set : { fieldB : "**someValue**" } }, { upsert : **true** } )         | 是                                                         |
| { fieldA：**1**， fieldB ：**1** } | db.collName.updateOne( { fieldA : **25**, fieldB : "**someValue**" }, { $set : { fieldC : **false** } }, { upsert : **true** } )    | 是                                                         |
| { fieldA ： **1** }              | db.collName.updateOne( { fieldA : { $lte : **25** } }, { $set : { fieldC : **true** } }, { upsert : **true** } )                    | 没有 查询谓词**fieldA**不等于                                      |
| { fieldA ： **1** }              | db.collName.updateOne( { fieldA : { $in : \[ **25** ] } }, { $set : { fieldA : **20** } }, { upsert : **true** } )                  | 没有 更新操作修改查询谓词中指定的字段。                                      |
| { \_id ： **1** }                | db.collName.updateOne( { fieldA : { $in : \[ **25** ] } }, { $set : { fieldA : **20** } }, { upsert : **true** } )                  | 没有 查询谓词字段集（**fieldA**）与索引关键字字段集（）不匹配\*\*\_id\*\*。         |
| { fieldA ： **1** }              | db.collName.updateOne( { fieldA : 25, fieldC : **true** }, { $set : { fieldD : **false** } }, { upsert : **true** } )               | 没有 这组查询谓词的字段（**fieldA**，**fieldC**）不匹配组索引键的字段（**fieldA**） |

在MongoDB 4.2之前，MongoDB可重试写不支持由于重复的键错误而失败的重试更新。

### 诊断程序

*版本3.6.3中的新功能*

[`serverStatus`](https://docs.mongodb.com/master/reference/command/serverStatus/#dbcmd.serverStatus)命令及其mongo shell帮助程序 [`db.serverStatus()`](https://docs.mongodb.com/master/reference/method/db.serverStatus/#db.serverStatus) 在[`transactions`](https://docs.mongodb.com/master/reference/command/serverStatus/#serverstatus.transactions)节中包含有关可重试写入的统计信息。

**针对本地数据库的可重试写入**

官方的MongoDB 4.2系列驱动程序默认情况下启用重试写入。 除非明确禁止重试写入，否则写入本地数据库的应用程序在升级到4.2系列驱动程序时将遇到写入错误。

要禁用可重试写入，请在MongoDB集群的[连接字符串](https://docs.mongodb.com/manual/reference/connection-string/#mongodb-uri)中指定[`retryWrites=false`](https://docs.mongodb.com/master/reference/connection-string/#urioption.retryWrites) 。

译者：杨帅

校对：杨帅


# 可重试读取

**在本页面**

* [前提条件](#prerequisites)
* [启用可重试读取](#enabling-retryable-reads)
* [可重试的读取操作](#retryable-read-operations)
* [行为](#behavior)

可重试读取允许MongoDB驱动程序在遇到某些网络或服务器错误时，可以一次自动重试某些读取操作。

## 前提条件

### 最小驱动程序版本

​ 官方MongoDB驱动兼容MongoDB服务器4.2和以后支持重试读取。

​ 有关官方MongoDB驱动程序的更多信息，请参阅 [MongoDB驱动程序](https://docs.mongodb.com/drivers/)。

### 最低服务器版本

​ 如果连接到MongoDB Server 3.6或更高版本，驱动程序只能重试读取操作。

## 启用可重试读取

官方MongoDB驱动程序兼容MongoDB服务器4.2和以后默认启用可重试读取。要显式禁用可重试读取，请在部署的[连接字符串中](https://docs.mongodb.com/manual/reference/connection-string/#mongodb-uri)中指定[`retryReads=false`](https://docs.mongodb.com/manual/reference/connection-string/#urioption.retryReads)。

在[`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo)shell不支持重试读取。

## 可重试的读取操作

MongoDB驱动程序支持重试以下读取操作。列表引用了每个方法的通用描述。对于特定的语法和用法，请遵循该方法的驱动程序文档。

| 方法                                                                                                                                                       | 内容描述          |
| -------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
| Collection.aggregate Collection.count Collection.countDocuments Collection.distinct Collection.estimatedDocumentCount Collection.find Database.aggregate | CRUD API读取操作. |

对于`Collection.aggregate`和`Database.aggregate`，驱动程序只能重试不包括写阶段的聚合管道，如[$out](https://docs.mongodb.com/manual/reference/operator/aggregation/out/#pipe._S_out)或[$merge](https://docs.mongodb.com/manual/reference/operator/aggregation/merge/#pipe._S_merge)。

|                                                                           |              |
| ------------------------------------------------------------------------- | ------------ |
| Collection.watch Database.watch MongoClient.watch                         | 更改流操作        |
| MongoClient.listDatabases Database.listCollections Collection.listIndexes | 枚举操作         |
| GridFS操作由`Collection.find` （ 例如`GridFSBucket.openDownloadStream`）支持       | GridFS文件下载操作 |

MongoDB驱动程序可能包括对其他操作的可重试支持，比如帮助方法或包装可重试读操作的方法。根据[驱动程序文档](https://docs.mongodb.com/drivers/) 确定方法是否显式支持可重试读取。

也可以看看:

可重试读规范:[支持的读取操作](https://github.com/mongodb/specifications/blob/master/source/retryable-reads/retryable-reads.rst#supported-read-operations).

#### 不支持的读取操作

以下操作不支持可重试的读取：

* [db.collection.mapReduce()](https://docs.mongodb.com/manual/reference/method/db.collection.mapReduce/#db.collection.mapReduce)
* [getMore](https://docs.mongodb.com/manual/reference/command/getMore/#dbcmd.getMore)
* 传递给通用**Database.runCommand**帮助器的任何读命令，它与读或写命令无关。

## 行为

### 持久性网络错误

MongoDB可重试读取只做一次重试尝试。这有助于解决暂时的网络错误或[复制集选举](https://docs.mongodb.com/manual/core/replica-set-elections/#replica-set-elections)，但不能解决持久的网络错误。

### 故障转移期间

在重试读取操作之前，驱动程序使用read命令的原始[读取首选项](https://docs.mongodb.com/manual/core/read-preference/#read-preference)执行[服务器选择](https://docs.mongodb.com/manual/core/read-preference-mechanics/#replica-set-read-preference-behavior)。如果驱动程序不能选择使用原始读取首选项进行重试的服务器，则驱动程序返回原始错误。

驱动程序在执行服务器选择之前等待[`serverSelectionTimeoutMS`](https://docs.mongodb.com/master/reference/connection-string/#urioption.serverSelectionTimeoutMS)毫秒。可重试读取不会处理在等待[`serverSelectionTimeoutMS`](https://docs.mongodb.com/master/reference/connection-string/#urioption.serverSelectionTimeoutMS)后不存在合格服务器的实例。

译者：杨帅

校对：杨帅


# SQL到MongoDB的映射图表

**在本页面**

* [术语和概念](#terminology)
* [可执行性文件](#Executables)
* [例子](#Examples)
* [进一步阅读](#Reading)

除了下面的图表之外，您可能需要考虑有关MongoDB的常见问题的常见问题部分。

## 术语和概念

下表介绍了各种SQL术语和概念以及相应的MongoDB术语和概念。

| SQL术语/概念                        | MongoDB术语/概念                                                                                                                                                                                                                                         |
| ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| database                        | [database](https://docs.mongodb.com/manual/reference/glossary/#term-database)                                                                                                                                                                        |
| table                           | [collection](https://docs.mongodb.com/manual/reference/glossary/#term-collection)                                                                                                                                                                    |
| row                             | [document](https://docs.mongodb.com/manual/reference/glossary/#term-document) or [BSON](https://docs.mongodb.com/manual/reference/glossary/#term-bson) document                                                                                      |
| column                          | [field](https://docs.mongodb.com/manual/reference/glossary/#term-field)                                                                                                                                                                              |
| index                           | [index](https://docs.mongodb.com/manual/reference/glossary/#term-index)                                                                                                                                                                              |
| table joins                     | [$lookup](https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/#pipe._S_lookup), 嵌入文档                                                                                                                                               |
| primary key （指定任何唯一的列或列组合作为主键。） | [primary key](https://docs.mongodb.com/manual/reference/glossary/#term-primary-key) （在MongoDB中，主键自动设置为\_id字段。）                                                                                                                                       |
| aggregation (e.g. group by)     | aggregation pipeline See the [SQL to Aggregation Mapping Chart](https://docs.mongodb.com/manual/reference/sql-aggregation-comparison/).                                                                                                              |
| SELECT INTO NEW\_TABLE          | [$out](https://docs.mongodb.com/manual/reference/operator/aggregation/out/#pipe._S_out) See the [SQL to Aggregation Mapping Chart](https://docs.mongodb.com/manual/reference/sql-aggregation-comparison/).                                           |
| MERGE INTO TABLE                | [$merge](https://docs.mongodb.com/manual/reference/operator/aggregation/merge/#pipe._S_merge) (Available starting in MongoDB 4.2) See the [SQL to Aggregation Mapping Chart](https://docs.mongodb.com/manual/reference/sql-aggregation-comparison/). |
| Transactions                    | [transactions](https://docs.mongodb.com/manual/core/transactions/) 在许多情况下，非规范化数据模型（嵌入式文档和数组） 将继续是您数据和用例的最佳选择，而不是多文档事务。 也就是说，在许多情况下，对数据进行适当的建模将最 大程度地减少对多文档交易的需求。                                                                                     |

## 可执行文件

下表展示了一些数据库可执行文件和相应的MongoDB可执行文件。这个表格并不是详尽无遗的。

|                 | MongoDB                                                                        | MySQL  | Oracle  | Informix  | DB2        |
| --------------- | ------------------------------------------------------------------------------ | ------ | ------- | --------- | ---------- |
| Database Server | [mongod](https://docs.mongodb.com/manual/reference/program/mongod/#bin.mongod) | mysqld | oracle  | IDS       | DB2 Server |
| Database Client | [mongo](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo)    | mysql  | sqlplus | DB-Access | DB2 Client |

## 例子

下表展示了各种SQL语句和相应的MongoDB语句。表中的例子假设以下条件:

* SQL示例假设有一个名为**people**的表。
* MongoDB示例假设一个名为**people**的集合，它包含以下原型的文档:

```
 { 
       _id: ObjectId("509a8fb2f3f4948bd2f983a0"),
       user_id: "abc123",
       age: 55,
       status: 'A'
 }
```

### 创建和修改

下表展示了与表级操作相关的各种SQL语句以及相应的MongoDB语句。

| SQL Schema语句                                                                                                                                              | MongoDB Schema语句                                                                                                                                                                                                                                                                                                                                                                                          |
| --------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **CREATE** **TABLE** people ( id MEDIUMINT **NOT** **NULL** AUTO\_INCREMENT, user\_id Varchar(30), age Number, status char(1), **PRIMARY** **KEY** (id) ) | 隐式创建的第一个[`insertOne()`](https://docs.mongodb.com/master/reference/method/db.collection.insertOne/#db.collection.insertOne)或[`insertMany()`](https://docs.mongodb.com/master/reference/method/db.collection.insertMany/#db.collection.insertMany)操作。如果没有指定\*\*\_id\*\*字段，则会自动添加主键\_id。 db.people.insertOne( { user\_id: "abc123", age: 55, status: "A" } ) 但是，您也可以显式地创建一个集合: db.createCollection("people") |
| **ALTER** **TABLE** people **ADD** join\_date DATETIME                                                                                                    | 集合不描述或不强制其文件结构； 即在集合级别没有结构上的更改。 但是，在文档级别，[updateMany()](https://docs.mongodb.com/manual/reference/method/db.collection.updateMany/#db.collection.updateMany)操作可以使用[$set](https://docs.mongodb.com/manual/reference/operator/update/set/#up._S_set)运算符将字段添加到现有文档中。 db.people.updateMany( { }, { $set: { join\_date: **new** Date() } } )                                                                   |
| **ALTER** **TABLE** people **DROP** **COLUMN** join\_date                                                                                                 | 集合不描述或不强制其文件结构； 即在集合级别没有结构上的更改。 但是，在文档级别，[updateMany()](https://docs.mongodb.com/manual/reference/method/db.collection.updateMany/#db.collection.updateMany)操作可以使用[$unset](https://docs.mongodb.com/manual/reference/operator/update/unset/#up._S_unset)运算符将字段添加到现有文档中。 db.people.updateMany( { }, { $unset: { "join\_date": "" } } )                                                                     |
| **CREATE** **INDEX** idx\_user\_id\_asc **ON** people(user\_id)                                                                                           | db.people.createIndex( { user\_id: 1 } )                                                                                                                                                                                                                                                                                                                                                                  |
| **CREATE** **INDEX** idx\_user\_id\_asc\_age\_desc **ON** people(user\_id, age **DESC**)                                                                  | db.people.createIndex( { user\_id: 1, age: -1 } )                                                                                                                                                                                                                                                                                                                                                         |
| **DROP** **TABLE** people                                                                                                                                 | db.people.drop()                                                                                                                                                                                                                                                                                                                                                                                          |

有关使用的方法和运算符的更多信息，请参见：

|                                                                                                                                   |                                                                                                                                      |                                                                                        |
| --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------- |
| [db.collection.insertOne()](https://docs.mongodb.com/manual/reference/method/db.collection.insertOne/#db.collection.insertOne)    | [db.collection.updateMany()](https://docs.mongodb.com/manual/reference/method/db.collection.updateMany/#db.collection.updateMany)    | [$set](https://docs.mongodb.com/manual/reference/operator/update/set/#up._S_set)       |
| [db.collection.insertMany()](https://docs.mongodb.com/manual/reference/method/db.collection.insertMany/#db.collection.insertMany) | [db.collection.createIndex()](https://docs.mongodb.com/manual/reference/method/db.collection.createIndex/#db.collection.createIndex) | [$unset](https://docs.mongodb.com/manual/reference/operator/update/unset/#up._S_unset) |
| [db.createCollection()](https://docs.mongodb.com/manual/reference/method/db.createCollection/#db.createCollection)                | [db.collection.drop()](https://docs.mongodb.com/manual/reference/method/db.collection.drop/#db.collection.drop)                      |                                                                                        |

**另看：**

* [Databases and Collections](https://docs.mongodb.com/manual/core/databases-and-collections/)
* [Documents](https://docs.mongodb.com/manual/core/document/)
* [Indexes](https://docs.mongodb.com/manual/indexes/)
* [Data Modeling Concepts](https://docs.mongodb.com/manual/core/data-models/)

#### 插入

下表显示了与将记录插入表和相应的MongoDB语句有关的各种SQL语句。

|                                                                                  |                                                                     |
| -------------------------------------------------------------------------------- | ------------------------------------------------------------------- |
| SQL INSERT语句                                                                     | **MongoDB insertOne() Statements**                                  |
| **INSERT** **INTO** people(user\_id, age, status) **VALUES** ("bcd001", 45, "A") | db.people.insertOne( { user\_id: "bcd001", age: 45, status: "A" } ) |

有关更多信息，请参见[`db.collection.insertOne()`](https://docs.mongodb.com/manual/reference/method/db.collection.insertOne/#db.collection.insertOne)。

也可以看看：

* [`Insert Documents`](https://docs.mongodb.com/manual/tutorial/insert-documents/)
* [`db.collection.insertMany()`](https://docs.mongodb.com/manual/reference/method/db.collection.insertMany/#db.collection.insertMany)
* [`Databases and Collections`](https://docs.mongodb.com/manual/core/databases-and-collections/)
* [`Documents`](https://docs.mongodb.com/manual/core/document/)

#### 选择

下表展示了与从表中读取记录相关的各种SQL语句以及相应的MongoDB语句。

> **注意**
>
> 除非通过投影明确排除，否则\[[`find()`](https://docs.mongodb.com/master/reference/method/db.collection.find/#db.collection.find)方法始终在返回的文档中包含\*\*\_id**字段。 下面的某些SQL查询可能包含一个**\_id\*\*字段来反映这一点，即使该字段未包含在相应的[`find()`](https://docs.mongodb.com/master/reference/method/db.collection.find/#db.collection.find)查询中也是如此。

| SQL SELECT 语句                                                                              | MongoDB find() 语句                                                                                                                                                                                                                             |
| ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **SELECT** *\*FROM* people                                                                 | db.people.find()                                                                                                                                                                                                                              |
| **SELECT** id, user\_id, status **FROM** people                                            | db.people.find( { }, { user\_id: 1, status: 1 } )                                                                                                                                                                                             |
| **SELECT** user\_id, status **FROM** people                                                | db.people.find( { }, { user\_id: 1, status: 1, \_id: 0 } )                                                                                                                                                                                    |
| **SELECT** ***FROM** people* *\*WHERE* status = "A"                                        | db.people.find( { status: "A" } )                                                                                                                                                                                                             |
| **SELECT** user\_id, status **FROM** people **WHERE** status = "A"                         | db.people.find( { status: "A" }, { user\_id: 1, status: 1, \_id: 0 } )                                                                                                                                                                        |
| **SELECT** ***FROM** people* *\*WHERE* status != "A"                                       | db.people.find( { status: { $ne: "A" } } )                                                                                                                                                                                                    |
| **SELECT** ***FROM** people* ***WHERE** status = "A"* *\*AND* age = 50                     | db.people.find( { status: "A", age: 50 } )                                                                                                                                                                                                    |
| **SELECT** ***FROM** people* ***WHERE** status = "A"* *\*OR* age = 50                      | db.people.find( { $or: \[ { status: "A" } , { age: 50 } ] } )                                                                                                                                                                                 |
| **SELECT** ***FROM** people* *\*WHERE* age > 25                                            | db.people.find( { age: { $gt: 25 } } )                                                                                                                                                                                                        |
| **SELECT** ***FROM** people* *\*WHERE* age < 25                                            | db.people.find( { age: { $lt: 25 } } )                                                                                                                                                                                                        |
| **SELECT** ***FROM** people* ***WHERE** age > 25* *\*AND* age <= 50                        | db.people.find( { age: { $gt: 25, $lte: 50 } } )                                                                                                                                                                                              |
| **SELECT** ***FROM** people* ***WHERE** user\_id \*like* "%bc%"                            | db.people.find( { user\_id: /bc/ } )\_ *\_or* db.people.find( { user\_id: { $regex: /bc/ } } )                                                                                                                                                |
| **SELECT** ***FROM** people* ***WHERE** user\_id \*like* "bc%"                             | db.people.find( { user\_id: /^bc/ } )\_ *\_or* db.people.find( { user\_id: { $regex: /^bc/ } } )                                                                                                                                              |
| **SELECT** ***FROM** people* ***WHERE** status = "A"* ***ORDER*** ***BY** user\_id \*ASC*  | db.people.find( { status: "A" } ).sort( { user\_id: 1 } )                                                                                                                                                                                     |
| **SELECT** ***FROM** people* ***WHERE** status = "A"* ***ORDER*** ***BY** user\_id \*DESC* | db.people.find( { status: "A" } ).sort( { user\_id: -1 } )                                                                                                                                                                                    |
| **SELECT** **COUNT**(*)* *\*FROM* people                                                   | db.people.count() *or* db.people.find().count()                                                                                                                                                                                               |
| **SELECT** **COUNT**(user\_id) **FROM** people                                             | db.people.count( { user\_id: { $exists: **true** } } )\_ *\_or* db.people.find( { user\_id: { $exists: **true** } } ).count()                                                                                                                 |
| **SELECT** **COUNT**(*)* ***FROM** people* *\*WHERE* age > 30                              | db.people.count( { age: { $gt: 30 } } ) *or* db.people.find( { age: { $gt: 30 } } ).count()                                                                                                                                                   |
| **SELECT** **DISTINCT**(status) **FROM** people                                            | db.people.aggregate( \[ { $group : { \_id : "$status" } } ] ) or, for distinct value sets that do not exceed the [BSON size limit](https://docs.mongodb.com/manual/reference/limits/#limit-bson-document-size) db.people.distinct( "status" ) |
| **SELECT** ***FROM** people* *\*LIMIT* 1                                                   | db.people.findOne() *or* db.people.find().limit(1)                                                                                                                                                                                            |
| **SELECT** ***FROM** people* *\*LIMIT* 5 SKIP 10                                           | db.people.find().limit(5).skip(10)                                                                                                                                                                                                            |
| **EXPLAIN** **SELECT** ***FROM** people* *\*WHERE* status = "A"                            | db.people.find( { status: "A" } ).explain()                                                                                                                                                                                                   |

有关使用的方法和运算符的更多信息，请参见：

|                                                                                                                                |                                                                                             |
| ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------- |
| .[`db.collection.find()`](https://docs.mongodb.com/manual/reference/method/db.collection.find/#db.collection.find)             | .[`$ne`](https://docs.mongodb.com/manual/reference/operator/query/ne/#op._S_ne)             |
| .[`db.collection.distinct()`](https://docs.mongodb.com/manual/reference/method/db.collection.distinct/#db.collection.distinct) | .[`$and`](https://docs.mongodb.com/manual/reference/operator/query/and/#op._S_and)          |
| .[`db.collection.findOne()`](https://docs.mongodb.com/manual/reference/method/db.collection.findOne/#db.collection.findOne)    | .[`$or`](https://docs.mongodb.com/manual/reference/operator/query/or/#op._S_or)             |
| .[`limit()`](https://docs.mongodb.com/manual/reference/method/cursor.limit/#cursor.limit)                                      | .[`$gt`](https://docs.mongodb.com/manual/reference/operator/query/gt/#op._S_gt)             |
| .[`skip()`](https://docs.mongodb.com/manual/reference/method/cursor.skip/#cursor.skip)                                         | .[`$lt`](https://docs.mongodb.com/manual/reference/operator/query/lt/#op._S_lt)             |
| .[`explain()`](https://docs.mongodb.com/manual/reference/method/cursor.explain/#cursor.explain)                                | .[`$exists`](https://docs.mongodb.com/manual/reference/operator/query/exists/#op._S_exists) |
| .[`sort()`](https://docs.mongodb.com/manual/reference/method/cursor.sort/#cursor.sort)                                         | .[`$lte`](https://docs.mongodb.com/manual/reference/operator/query/lte/#op._S_lte)          |
| .[`count()`](https://docs.mongodb.com/manual/reference/method/cursor.count/#cursor.count)                                      | .[`$regex`](https://docs.mongodb.com/manual/reference/operator/query/regex/#op._S_regex)    |

另看：

* [Query Documents](https://docs.mongodb.com/manual/tutorial/query-documents/)
* [Query and Projection Operators](https://docs.mongodb.com/manual/reference/operator/query/)
* [mongo Shell Methods](https://docs.mongodb.com/manual/reference/method/)

#### 更新记录

下表显示了与更新表中的现有记录和相应的MongoDB语句有关的各种SQL语句。

|                                                                |                                                                         |
| -------------------------------------------------------------- | ----------------------------------------------------------------------- |
| **SQL Update Statements**                                      | **MongoDB updateMany() Statements**                                     |
| **UPDATE** people **SET** status = "C" **WHERE** age > 25      | db.people.updateMany( { age: { $gt: 25 } }, { $set: { status: "C" } } ) |
| **UPDATE** people **SET** age = age + 3 **WHERE** status = "A" | db.people.updateMany( { status: "A" } , { $inc: { age: 3 } } )          |

有关示例中使用的方法和运算符的更多信息，请参见：

* [db.collection.updateMany()](https://docs.mongodb.com/manual/reference/method/db.collection.updateMany/#db.collection.updateMany)
* [$gt](https://docs.mongodb.com/manual/reference/operator/query/gt/#op._S_gt)
* [$set](https://docs.mongodb.com/manual/reference/operator/update/set/#up._S_set)
* [$inc](https://docs.mongodb.com/manual/reference/operator/update/inc/#up._S_inc)

另看：

* [Update Documents](https://docs.mongodb.com/manual/tutorial/update-documents/)
* [Update Operators](https://docs.mongodb.com/manual/reference/operator/update/)
* [db.collection.updateOne()](https://docs.mongodb.com/manual/reference/method/db.collection.updateOne/#db.collection.updateOne)
* [db.collection.replaceOne()](https://docs.mongodb.com/manual/reference/method/db.collection.replaceOne/#db.collection.replaceOne)

#### 删除记录

下表显示了与从表中删除记录和相应的MongoDB语句有关的各种SQL语句。

|                                                   |                                         |
| ------------------------------------------------- | --------------------------------------- |
| **SQL Delete Statements**                         | **MongoDB deleteMany() Statements**     |
| **DELETE** **FROM** people **WHERE** status = "D" | db.people.deleteMany( { status: "D" } ) |
| **DELETE** **FROM** people                        | db.people.deleteMany({})                |

获得更多信息，请参见：[db.collection.deleteMany()](https://docs.mongodb.com/manual/reference/method/db.collection.deleteMany/#db.collection.deleteMany).

另看：

* [Delete Documents](https://docs.mongodb.com/manual/tutorial/remove-documents/)
* [db.collection.deleteOne()](https://docs.mongodb.com/manual/reference/method/db.collection.deleteOne/#db.collection.deleteOne)

#### 进一步阅读

如果您正在考虑将SQL应用程序迁移到MongoDB，请下载[《 MongoDB应用程序现代化指南》](https://www.mongodb.com/modernize?tck=docs_server)。

下载内容包括以下资源：

* 演示使用MongoDB进行数据建模的方法
* 白皮书涵盖了从RDBMS数据模型迁移到MongoDB的最佳实践和注意事项
* 参考MongoDB模式及其等效RDBMS
* 应用程序现代化记分卡

译者：杨帅

校对：杨帅


# 文本搜索

**在本页面**

* [总览](#Overview)
* [例子](#Example)
* [语言支持](#Language)

> MONGODB ATLAS搜索
>
> [Atlas搜索](https://docs.atlas.mongodb.com/atlas-search)可以很容易地在MongoDB数据上构建快速、基于相关性的搜索功能。今天就在[MongoDB Atlas](https://www.mongodb.com/cloud/atlas?tck=docs_server),上试试吧，我们的完全托管数据库是一种服务。

## 总览

MongoDB支持执行字符串内容的文本搜索的查询操作。 为了执行文本搜索，MongoDB使用文本索引和[`$text`](/mongodb-crud-operations/text-search)运算符。

> **\[success] Note**
>
> 视图不支持文本搜索

## 例子

此示例演示了如何在仅指定文本字段的情况下构建文本索引并使用它来coffee shops。

使用以下文档创建一个集合存储：

```
  db.stores.insert(
          [
              { _id: 1, name: "Java Hut", description: "Coffee and cakes" },
              { _id: 2, name: "Burger Buns", description: "Gourmet hamburgers" },
              { _id: 3, name: "Coffee Shop", description: "Just coffee" },  
              { _id: 4, name: "Clothes Clothes Clothes", description: "Discount clothing" }, 
              { _id: 5, name: "Java Shopping", description: "Indonesian goods" } 
          ]
  )
```

### 文字索引

MongoDB提供了[文本索引](https://docs.mongodb.com/master/core/index-text/#index-feature-text)来支持对字符串内容的文本搜索查询。文本索引可以包含值为字符串或字符串元素数组的任何字段。

要执行文本搜索查询，您必须在集合上有一个文本索引。一个集合只能有一个文本搜索索引，但是该索引可以覆盖多个字段。

例如，您可以在[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell中运行以下命令，以允许在名称和描述字段中进行文本搜索：

```
db.stores.createIndex( { name: "text", description: "text" } )
```

### $text运算符

使用[`$text`](https://docs.mongodb.com/master/reference/operator/query/text/#op._S_text)查询操作符对具有文本索引的集合执行[文本索引](https://docs.mongodb.com/master/core/index-text/#index-feature-text)。

[`$text`](https://docs.mongodb.com/master/reference/operator/query/text/#op._S_text) 将使用空格和大多数标点作为分隔符对搜索字符串进行标记，并在搜索字符串中对所有这些标记执行逻辑或操作。

例如，您可以使用以下查询来查找包含“coffee”、“shop”和“java”列表中任何术语的所有商店:

```
db.stores.find( { $text: { $search: "java coffee shop" } } )
```

### 准确的短语

您还可以通过将短语包装在双引号中来搜索精确的短语。如果\*\*$search\*\*字符串包含一个短语和单个术语，文本搜索将只匹配包含该短语的文档。

例如，以下将查找包含“coffee shop”的所有文档：

```
db.stores.find( { $text: { $search: "\"coffee shop\"" } } )
```

更多信息参见：请看[Phrases](https://docs.mongodb.com/manual/reference/operator/query/text/#text-operator-phrases).

### 期限排除

要排除一个单词，可以在前面加上一个“-”字符。例如，要查找所有包含“java”或“shop”但不包含“coffee”的商店，请使用以下方法:

```
db.stores.find( { $text: { $search: "java shop -coffee" } } )
```

### 排序

默认情况下，MongoDB将以无序的顺序返回结果。但是，文本搜索查询将为每个文档计算一个相关性分数，该分数指定文档与查询的匹配程度。

为了排序的结果在相关性分数的顺序，你必须明确项目[`$meta`](https://docs.mongodb.com/master/reference/operator/aggregation/meta/#proj._S_meta) **textScore**字段和排序:

```
db.stores.find( 
      { $text: { $search: "java coffee shop" } },
      { score: { $meta: "textScore" } }
  ).sort( { score: { $meta: "textScore" } } )
```

文本搜索也可以在聚合管道中使用。

## 语言支持

MongoDB支持多种语言的文本搜索。 有关支持的语言列表，请参见[文本搜索语言](https://docs.mongodb.com/manual/reference/text-search-languages/)。

译者：杨帅

校对：杨帅


# 文本索引


# 文本索引操作

**在本页面**

* [查询框架](#query)
* [聚合框架](#aggregation)

> **\[success] Note**
>
> 视图不支持文本搜索。

## 查询框架

使用[`$text`](https://docs.mongodb.com/master/reference/operator/query/text/#op._S_text)查询操作符对具有文本索引的集合执行文本搜索。

[`$text`](https://docs.mongodb.com/master/reference/operator/query/text/#op._S_text)将使用空格和大多数标点作为分隔符对搜索字符串进行标记，并在搜索字符串中对所有这些标记执行逻辑或操作。

例如，您可以使用以下查询来查找包含“coffee”、“shop”和“java”列表中任何术语的所有商店:

```
db.stores.find( { $text: { $search: "java coffee shop" } } )
```

使用[`$meta`](https://docs.mongodb.com/master/reference/operator/aggregation/meta/#proj._S_meta)查询操作符获取每个匹配文档的相关性分数并进行排序。例如，要按相关性排序一份coffee shops 列表，运行以下命令:

```
db.stores.find(
          { $text: { $search: "coffee shop cake" } },
          { score: { $meta: "textScore" } }
 ).sort( { score: { $meta: "textScore" } } )
```

有关 [`$text`](https://docs.mongodb.com/master/reference/operator/query/text/#op._S_text) 和[`$meta`](https://docs.mongodb.com/master/reference/operator/aggregation/meta/#proj._S_meta) 操作符的更多信息，包括限制和行为，请参见:

* [$text 参考页面](https://docs.mongodb.com/manual/reference/operator/query/text/#op._S_text)
* [$text 查询示例](https://docs.mongodb.com/manual/reference/operator/query/text/#text-query-examples)
* [$meta](https://docs.mongodb.com/manual/reference/operator/projection/meta/#proj._S_meta) projection operator

## 聚合框架

在使用[聚合](https://docs.mongodb.com/master/aggregation/)框架时，使用[`$match`](https://docs.mongodb.com/master/reference/operator/aggregation/match/#pipe._S_match) 和[`$text`](https://docs.mongodb.com/master/reference/operator/query/text/#op._S_text) 表达式来执行文本搜索查询。要按照相关性评分对结果排序，请在[`$sort`](https://docs.mongodb.com/master/reference/operator/aggregation/sort/#pipe._S_sort) 阶段使用[`$meta`](https://docs.mongodb.com/master/reference/operator/aggregation/meta/#exp._S_meta)聚合操作符

有关聚合框架中文本搜索的更多信息和示例，请参见[聚合管道中的文本搜索](https://docs.mongodb.com/manual/tutorial/text-search-in-aggregation/).。

译者：杨帅

校对：杨帅


# 集合管道中的文本索引

**在本页面：**

* [限制条件](#Restrictions)
* [文字分数](#Text)
* [计算包含单词的文章的总浏览量](#Calculate)
* [返回结果按文本搜索分数排序](#Return)
* [文字分数匹配](#Match)
* [指定用于文本搜索的语言](#Specify)

在聚合管道中，可以在[`$match`](https://docs.mongodb.com/master/reference/operator/aggregation/match/#pipe._S_match) 阶段使用[`$text`](https://docs.mongodb.com/master/reference/operator/query/text/#op._S_text)查询运算符来进行文本搜索。

## 限制条件

有关常规的[`$text`](https://docs.mongodb.com/master/reference/operator/query/text/#op._S_text) 运算符限制，请参见[运算符限制](https://docs.mongodb.com/manual/reference/operator/query/text/#text-query-operator-behavior)。

此外，聚合管道中的文本搜索具有以下限制：

* 包含[`$text`](https://docs.mongodb.com/master/reference/operator/query/text/#op._S_text)的[`$match`](https://docs.mongodb.com/master/reference/operator/aggregation/match/#pipe._S_match)阶段必须是管道中的第一个阶段。
* 文本运算符在阶段只能出现一次。
* 文本运算符表达式不能出现在[`$or`](https://docs.mongodb.com/master/reference/operator/aggregation/or/#exp._S_or) 或[`$not`](https://docs.mongodb.com/master/reference/operator/aggregation/not/#exp._S_not) 表达式中。
* 默认情况下，文本搜索不会按匹配分数的顺序返回匹配的文档。在[`$sort`](https://docs.mongodb.com/master/reference/operator/aggregation/sort/#pipe._S_sort)阶段使用[`$meta`](https://docs.mongodb.com/master/reference/operator/aggregation/meta/#exp._S_meta)聚合表达式。

## 文字分数

[`$text`](https://docs.mongodb.com/master/reference/operator/query/text/#op._S_text)操作符为索引字段中包含搜索词的每个文档分配一个分数。分数表示文档与给定文本搜索查询的相关性。分数可以是[`$sort`](https://docs.mongodb.com/master/reference/operator/aggregation/sort/#pipe._S_sort)管道规范的一部分，也可以是投影表达式的一部分。\*\*{$meta: "textScore"}\*\*表达式提供处理[`$text`](https://docs.mongodb.com/master/reference/operator/query/text/#op._S_text)操作的信息。有关访问投射或排序分数的详细信息，请参阅[`$meta`](https://docs.mongodb.com/master/reference/operator/aggregation/meta/#exp._S_meta) 。

元数据仅在包含 [`$text`](https://docs.mongodb.com/master/reference/operator/query/text/#op._S_text) 操作的[`$match`](https://docs.mongodb.com/master/reference/operator/aggregation/match/#pipe._S_match)阶段之后可用。

### 例子

以下示例假定集合`articles`在字段`subject`上具有文本索引：

```
 db.articles.createIndex( { subject: "text" } )
```

## 计算包含单词的文章的总浏览量

下面的聚合在[`$match`](https://docs.mongodb.com/master/reference/operator/aggregation/match/#pipe._S_match)阶段搜索术语cake，并在[`$group`](https://docs.mongodb.com/master/reference/operator/aggregation/group/#pipe._S_group) 阶段计算匹配文档的总视图。

```
 db.articles.aggregate(
      [
        { $match: { $text: { $search: "cake" } } },
        { $group: { _id: **null**, views: { $sum: "$views" } } }
      ]
  )
```

## 返回结果按文本搜索分数排序

要根据文本搜索分数进行排序，在[`$sort`](https://docs.mongodb.com/master/reference/operator/aggregation/sort/#pipe._S_sort) 阶段包含[`{$meta: "textScore"}`](https://docs.mongodb.com/master/reference/operator/aggregation/meta/#exp._S_meta) 表达式。下面的示例匹配术语**cake**或**tea**，按**textScore**降序排序，并且只返回结果集中的**title**字段。

```
db.articles.aggregate(
    [
      { $match: { $text: { $search: "cake tea" } } }, 
      { $sort: { score: { $meta: "textScore" } } }, 
      { $project: { title: 1, _id: 0 } } 
    ]
  )
```

指定的元数据决定排序顺序。例如，\*\*“textScore”\*\*元数据按降序排序。有关元数据的更多信息以及覆盖元数据的默认排序顺序的示例，请参见[`$meta`](https://docs.mongodb.com/master/reference/operator/aggregation/meta/#exp._S_meta)。

## 文字分数匹配

\*\*“textScore”\*\*元数据可用于包括[`$text`](https://docs.mongodb.com/master/reference/operator/query/text/#op._S_text) 操作的[`$match`](https://docs.mongodb.com/master/reference/operator/aggregation/match/#pipe._S_match) 阶段之后的投影、排序和条件。

下面的示例匹配术语**cake**或**tea**，投影标题和分数字段，然后只返回分数大于**1.0**的文档。

```
 db.articles.aggregate(
    [
        { $match: { $text: { $search: "cake tea" } } },
        { $project: { title: 1, _id: 0, score: { $meta: "textScore" } } },
        { $match: { score: { $gt: 1.0 } } }
    ]
 )
```

## 指定用于文本搜索的语言

下面的聚合在[`$match`](https://docs.mongodb.com/master/reference/operator/aggregation/match/#pipe._S_match) 阶段中以西班牙语搜索包含术语**saber**而不是术语**claro**的文档，并计算[`$group`](https://docs.mongodb.com/master/reference/operator/aggregation/group/#pipe._S_group) 阶段中匹配文档的总视图。

```
db.articles.aggregate(
    [   
            { $match: { $text: { $search: "saber -claro", $language: "es" } } }, 
            { $group: { _id: null, views: { $sum: "$views" } } } 
    ]
 )
```

​

译者：杨帅

校对：杨帅


# 文本索引语言

[文本索引](https://docs.mongodb.com/master/core/index-text/#index-feature-text) 和[`$text`](https://docs.mongodb.com/master/reference/operator/query/text/#op._S_text) 运算符可用于下列语言，并接受两个字母的ISO 639-1语言代码或语言名称的长形式:

| 语言名称         | ISO 639-1(双字母代码) |
| ------------ | ---------------- |
| `danish`     | `da`             |
| `dutch`      | `nl`             |
| `english`    | `en`             |
| `finnish`    | `fi`             |
| `french`     | `fr`             |
| `german`     | `de`             |
| `hungarian`  | `hu`             |
| `italian`    | `it`             |
| `norwegian`  | `nb`             |
| `portuguese` | `pt`             |
| `romanian`   | `ro`             |
| `russian`    | `ru`             |
| `spanish`    | `es`             |
| `swedish`    | `sv`             |
| `turkish`    | `tr`             |

> **\[success] Note**
>
> 如果指定语言值为\*\*“none”\*\*，则文本搜索使用简单的标记化，不包含停止词列表和词干分析。

另看：

[Specify a Language for Text Index](https://docs.mongodb.com/manual/tutorial/specify-language-for-text-index/)

译者：杨帅

校对：杨帅


# Read Concern读关注

**在本页面**

* [读关注级别](#级别)
* [ReadConcern 支持](#支持)
* [注意事项](#注意)

**读关注** 选项允许你控制从复制集和分片集群读取数据的一致性和隔离性。

通过有效地使用[写关注](https://docs.mongodb.com/manual/reference/write-concern/)和读关注，你可以适当地调整一致性和可用性的保证级别，例如等待以保证更强的一致性，或放松一致性要求以提供更高的可用性。

将MongoDB驱动程序更新到MongoDB 3.2或更高版本以支持读关注。

## 阅读关注级别

以下为可用的读关注级别：

|                                                                                                                         |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| ----------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `level`                                                                                                                 | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| [`"local"`](https://docs.mongodb.com/manual/reference/read-concern-local/#readconcern.%22local%22)                      | 查询并从实例返回数据，但不能保证该数据已被写入大多数副本集成员（即可能已经回滚）。 **默认为：** 针对主节点读。 如果读取与因果一致的会话相关联，则针对副节点读。 \*\*可用性：\*\*读关注`local`可用于有或没有[因果关系一致的会话](https://docs.mongodb.com/manual/core/read-isolation-consistency-recency/#sessions)和事务中。 更多的信息，请参考[`"local"`](https://docs.mongodb.com/manual/reference/read-concern-local/#readconcern.%22local%22)页                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| [`"available"`](https://docs.mongodb.com/manual/reference/read-concern-available/#readconcern.%22available%22)          | 查询并从实例返回数据，但不能保证该数据已被写入大多数副本集成员（即可能已经回滚）。 \*\*默认为：\*\*如果读取与[因果关系一致的会话](https://docs.mongodb.com/manual/core/read-isolation-consistency-recency/#sessions)没有关联，则针对副节点读 \*\*可用性：\*\*读关注`available`无法用于有因果关系一致的会话和事务中。 对于分片群集，[`"available"`](https://docs.mongodb.com/manual/reference/read-concern-available/#readconcern.%22available%22)读关注提供了各种读关注中尽可能最低的延迟。但是，这是以牺牲一致性为代价的，因为从分片的集合中进行读取时，[`"available"`](https://docs.mongodb.com/manual/reference/read-concern-available/#readconcern.%22available%22)读关注会返回[孤立的文档](https://docs.mongodb.com/manual/reference/glossary/#term-orphaned-document)。为了避免从分片的集合中读取时返回孤立文档的风险，可使用其他读关注，如[`"local"`](https://docs.mongodb.com/manual/reference/read-concern-local/#readconcern.%22local%22)读关注。 更多的信息，请参考[`"available"`](https://docs.mongodb.com/manual/reference/read-concern-available/#readconcern.%22available%22)页 *3.6版本的新功能*                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| [`"majority"`](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern.%22majority%22)             | 为了满足读关注“majority”，副本集成员从其内存视图中返回多数提交点提交的数据。这样，读关注[`"majority"`](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern.%22majority%22)在性能成本上可与其他读关注相媲美。 **可用性：** 读关注[`"majority"`](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern.%22majority%22)可用于有或没有因果关系一致的会话和事务中。 对于具有三名成员的主从仲裁（PSA）架构的部署，可以禁用读关注[`"majority"`](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern.%22majority%22)；但是，这对change streams（仅在MongoDB 4.0和更早版本中）和分片群集上的事务有影响。有关更多信息，请参见[禁用读关注Marjority](https://docs.mongodb.com/manual/reference/read-concern-majority/#disable-read-concern-majority).。 \*\*要求：\*\*若要使用[`"majority"`](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern.%22majority%22)的[读关注](https://docs.mongodb.com/manual/reference/glossary/#term-read-concern)级别，副本集必须使用WiredTiger存储引擎。 **注意：** 对于[多文档事务](https://docs.mongodb.com/manual/core/transactions/)中的操作，仅当事务以[写关注`"majority"`](https://docs.mongodb.com/manual/core/transactions/#transactions-write-concern)提交时，读关注[`"majority"`](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern.%22majority%22)才提供其保证。否则，[`"majority"`](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern.%22majority%22)读关注不能保证其在事务中读取的数据。 更多的信息，请参考[`"majority"`](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern.%22majority%22)页                                                                                                                                                                                                                                                                             |
| [`"linearizable"`](https://docs.mongodb.com/manual/reference/read-concern-linearizable/#readconcern.%22linearizable%22) | 该查询返回的数据表示了这些数据在操作开始之前已成功在大多数节点确认写入。查询可能会等待并发执行的写操作传播到大多数副本集成员，然后返回结果。 如果大多数副本集成员崩溃并在读操作后重新启动，则如果将[`writeConcernMajorityJournalDefault`](https://docs.mongodb.com/manual/reference/replica-configuration/#rsconf.writeConcernMajorityJournalDefault)设置为默认状态true，则读操作返回的文档将还是有效的。 将[`writeConcernMajorityJournalDefault`](https://docs.mongodb.com/manual/reference/replica-configuration/#rsconf.writeConcernMajorityJournalDefault)设置为`false`时，MongoDB不会等待[`w: "majority"`](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern.%22majority%22)在确认写入之前先要写入磁盘日志。这样，如果给定副本集中大多数节点的瞬时丢失（例如崩溃和重新启动），`majority`写操作可能会回滚。 **可用性：** 读关注[`"linearizable"`](https://docs.mongodb.com/manual/reference/read-concern-linearizable/#readconcern.%22linearizable%22)不适用于因果一致的会话和事务。 你可以仅对主节点上的读操作指定为线性读关注。 你不能将[`$out`](https://docs.mongodb.com/manual/reference/operator/aggregation/out/#pipe._S_out)或[`$merge`](https://docs.mongodb.com/manual/reference/operator/aggregation/merge/#pipe._S_merge)操作与读关注[`"linearizable"`](https://docs.mongodb.com/manual/reference/read-concern-linearizable/#readconcern.%22linearizable%22)结合使用。也就是说，如果为[`db.collection.aggregate()`](https://docs.mongodb.com/manual/reference/method/db.collection.aggregate/#db.collection.aggregate)指定为[`"linearizable"`](https://docs.mongodb.com/manual/reference/read-concern-linearizable/#readconcern.%22linearizable%22)读关注，则不能在管道中使用任何的操作。 \*\*要求：\*\*linearizable读关注仅保证在读操作指定了唯一标识单个文档的查询过滤器时可用。 请始终将`maxTimeMS`与linearizable读关注一起使用，以防止大多数数据承载成员不可用。`maxTimeMS`确保操作不会无限期地阻塞，而是确保如果无法满足读取要求，则操作将返回错误。 更多的信息，请参考[`"linearizable"`](https://docs.mongodb.com/manual/reference/read-concern-linearizable/#readconcern.%22linearizable%22)页 |
| [`"snapshot"`](https://docs.mongodb.com/manual/reference/read-concern-snapshot/#readconcern.%22snapshot%22)             | 如果事务不是[因果一致会话](https://docs.mongodb.com/manual/core/read-isolation-consistency-recency/#sessions)的一部分，写关注为[`"majority"`](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern.%22majority%22)且在事务提交后，可以确保事务操作已从多数提交数据的快照中读取。 如果事务是[因果一致会话](https://docs.mongodb.com/manual/core/read-isolation-consistency-recency/#sessions)的一部分，写关注为[`"majority"`](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern.%22majority%22)且在事务提交后，可以确保事务操作已从多数提交数据的快照中读取，该快照提供了与紧接事务开始之前的操作的因果一致性。 读关注[`"snapshot"`](https://docs.mongodb.com/manual/reference/read-concern-snapshot/#readconcern.%22snapshot%22)仅可用于多文档事务。 对于分片群集上的事务，如果事务中的任何操作涉及[已被禁用读关注“majority”](https://docs.mongodb.com/manual/reference/read-concern-majority/#disable-read-concern-majority)的分片，那你就不能对该事务使用读关注[`"snapshot"`](https://docs.mongodb.com/manual/reference/read-concern-snapshot/#readconcern.%22snapshot%22)。你只能对事务使用读关注[`"local"`](https://docs.mongodb.com/manual/reference/read-concern-local/#readconcern.%22local%22)或[`"majority"`](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern.%22majority%22)。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |

无论[读关注](https://docs.mongodb.com/manual/reference/glossary/#term-read-concern)级别如何，节点上的最新数据都可能无法反映系统中数据的最新版本

有关每个阅读关注级别的更多信息，请参见：

* [读关注 "local"](https://docs.mongodb.com/manual/reference/read-concern-local/)
* [读关注 "available"](https://docs.mongodb.com/manual/reference/read-concern-available/)
* [读关注 "majority"](https://docs.mongodb.com/manual/reference/read-concern-majority/)
* [读关注 "linearizable"](https://docs.mongodb.com/manual/reference/read-concern-linearizable/)
* [读关注 "snapshot"](https://docs.mongodb.com/manual/reference/read-concern-snapshot/)

## ReadConcern 支持

### 读关注选项

对于不在[多文档事务](https://docs.mongodb.com/manual/core/transactions/)中的操作，你可以将 `readConcern` 级别指定为一个命令和方法的选项：

```
readConcern: { level: <level> }
```

要为 [mongo](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo) shell方法 [db.collection.find()](https://docs.mongodb.com/manual/reference/method/db.collection.find/#db.collection.find) 指定阅读关注级别，请使用 [cursor.readConcern()](https://docs.mongodb.com/manual/reference/method/cursor.readConcern/#cursor.readConcern) 方法：

```
db.collection.find().readConcern(<level>)
```

### 事务和可用的读关注

对于[多文档事务](https://docs.mongodb.com/manual/core/transactions/)，应在事务级别而不是在单个操作级别设置读关注。事务中的操作将使用事务级别的读关注。事务内部将忽略在集合和数据库级别设置的任何读关注。如果显式指定了事务级别的读关注点，则在事务内部也将忽略客户端级别的读关注点。

### 重要

不要为各个操作明确设置读关注。要设置事务的读关注，请参阅读 [Read Concern/Write Concern/Read Preference](https://docs.mongodb.com/manual/core/transactions/#transaction-options)。

你可以在事务开始时设置读关注：

* 对于多文档事务，读关注级别[`"snapshot"`](https://docs.mongodb.com/manual/reference/read-concern-snapshot/#readconcern.%22snapshot%22), [`"local"`](https://docs.mongodb.com/manual/reference/read-concern-local/#readconcern.%22local%22) 和 [`"majority"`](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern.%22majority%22)是可用的。
* [多文档事务](https://docs.mongodb.com/manual/core/transactions/)中的写命令可以支持事务级别的读关注。

如果未在事务开始时指定，则事务将使用会话级的读关注，或者如果未设置，则使用客户端级的读关注。

有关等多信息，请参考 [事务的读关注](https://docs.mongodb.com/manual/core/transactions/#transactions-read-concern).

#### 因果一致的会话和阅读相关的担忧

对于在[因果一致的会话](https://docs.mongodb.com/manual/core/read-isolation-consistency-recency/#causal-consistency)中的操作，[`"local"`](https://docs.mongodb.com/manual/reference/read-concern-local/#readconcern.%22local%22) h和 [`"majority"`](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern.%22majority%22)级别可用。但是，为了保证因果一致性，你必须使用 [`"majority"`](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern.%22majority%22)。有关详细信息，请参见 [因果一致性](https://docs.mongodb.com/manual/core/read-isolation-consistency-recency/#causal-consistency)。

如果多文档事务与因果一致的会话相关联，则[`"snapshot"`](https://docs.mongodb.com/manual/reference/read-concern-snapshot/#readconcern.%22snapshot%22) 也可用于该事务。

#### 支持读关注的操作

下列的操作支持读关注：

#### 重要

在为事务中的操作设置读关注时，请在事务级别而不是在单个操作级别设置读关注。不要在事务中明确的设置单独操作的读关注。更多信息，查看[事务和读关注](https://docs.mongodb.com/manual/core/transactions/#transactions-read-concern)

|                                                                                                                                                                                                                                         |                                                                                                    |                                                                                                                |                                                                                                             |                                                                                                             |                                                                                                                         |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| 命令/方法                                                                                                                                                                                                                                   | [`"local"`](https://docs.mongodb.com/manual/reference/read-concern-local/#readconcern.%22local%22) | [`"available"`](https://docs.mongodb.com/manual/reference/read-concern-available/#readconcern.%22available%22) | [`"majority"`](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern.%22majority%22) | [`"snapshot"`](https://docs.mongodb.com/manual/reference/read-concern-snapshot/#readconcern.%22snapshot%22) | [`"linearizable"`](https://docs.mongodb.com/manual/reference/read-concern-linearizable/#readconcern.%22linearizable%22) |
| [`count`](https://docs.mongodb.com/manual/reference/command/count/#dbcmd.count)                                                                                                                                                         | ✓                                                                                                  | ✓                                                                                                              | ✓                                                                                                           |                                                                                                             | ✓                                                                                                                       |
| [`distinct`](https://docs.mongodb.com/manual/reference/command/distinct/#dbcmd.distinct)                                                                                                                                                | ✓                                                                                                  | ✓                                                                                                              | ✓                                                                                                           | ✓                                                                                                           | ✓                                                                                                                       |
| [`find`](https://docs.mongodb.com/manual/reference/command/find/#dbcmd.find)                                                                                                                                                            | ✓                                                                                                  | ✓                                                                                                              | ✓                                                                                                           | ✓                                                                                                           | ✓                                                                                                                       |
| [`db.collection.find()`](https://docs.mongodb.com/manual/reference/method/db.collection.find/#db.collection.find) via [`cursor.readConcern()`](https://docs.mongodb.com/manual/reference/method/cursor.readConcern/#cursor.readConcern) | ✓                                                                                                  | ✓                                                                                                              | ✓                                                                                                           | ✓                                                                                                           | ✓                                                                                                                       |
| [`geoSearch`](https://docs.mongodb.com/manual/reference/command/geoSearch/#dbcmd.geoSearch)                                                                                                                                             | ✓                                                                                                  | ✓                                                                                                              | ✓                                                                                                           | ✓                                                                                                           | ✓                                                                                                                       |
| [`getMore`](https://docs.mongodb.com/manual/reference/command/getMore/#dbcmd.getMore)                                                                                                                                                   | ✓                                                                                                  |                                                                                                                |                                                                                                             |                                                                                                             | ✓                                                                                                                       |
| [`aggregate`](https://docs.mongodb.com/manual/reference/command/aggregate/#dbcmd.aggregate) [`db.collection.aggregate()`](https://docs.mongodb.com/manual/reference/method/db.collection.aggregate/#db.collection.aggregate)            | ✓                                                                                                  | ✓                                                                                                              | ✓                                                                                                           | ✓                                                                                                           | ✓                                                                                                                       |
| [`Session.startTransaction()`](https://docs.mongodb.com/manual/reference/method/Session.startTransaction/#Session.startTransaction)                                                                                                     | ✓                                                                                                  |                                                                                                                | ✓                                                                                                           | ✓                                                                                                           |                                                                                                                         |

|                                                                      |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [\[1\]](https://docs.mongodb.com/manual/reference/read-concern/#id5) | 你不能将[`$out`](https://docs.mongodb.com/manual/reference/operator/aggregation/out/#pipe._S_out) 或者 [`$merge`](https://docs.mongodb.com/manual/reference/operator/aggregation/merge/#pipe._S_merge)阶段与读关注的[`"linearizable"`](https://docs.mongodb.com/manual/reference/read-concern-linearizable/#readconcern.%22linearizable%22)结合使用。也就是说，如果为[`db.collection.aggregate()`](https://docs.mongodb.com/manual/reference/method/db.collection.aggregate/#db.collection.aggregate)指定[`"linearizable"`](https://docs.mongodb.com/manual/reference/read-concern-linearizable/#readconcern.%22linearizable%22)读关注，则不能在管道中包括任何一个阶段。 |
| [\[2\]](https://docs.mongodb.com/manual/reference/read-concern/#id4) | 读关注[`"snapshot"`](https://docs.mongodb.com/manual/reference/read-concern-snapshot/#readconcern.%22snapshot%22)仅适用于多文档事务。在事务中，不能在分片集合上使用`distinct`命令或其协助命令。                                                                                                                                                                                                                                                                                                                                                                                                                                                               |

下列的写操作页能接受读关注，但必须是多文档事务的一部分：

#### 重要

在为事务中的操作设置读关注时，请在事务级别而不是在单个操作级别设置读关注

|                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |                                                                                                    |                                                                                                                |                                                                                                             |                                                                                                             |                                                                                                                         |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| Command 命令                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                | [`"local"`](https://docs.mongodb.com/manual/reference/read-concern-local/#readconcern.%22local%22) | [`"available"`](https://docs.mongodb.com/manual/reference/read-concern-available/#readconcern.%22available%22) | [`"majority"`](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern.%22majority%22) | [`"snapshot"`](https://docs.mongodb.com/manual/reference/read-concern-snapshot/#readconcern.%22snapshot%22) | [`"linearizable"`](https://docs.mongodb.com/manual/reference/read-concern-linearizable/#readconcern.%22linearizable%22) |
| [`delete`](https://docs.mongodb.com/manual/reference/command/delete/#dbcmd.delete) [`db.collection.deleteMany()`](https://docs.mongodb.com/manual/reference/method/db.collection.deleteMany/#db.collection.deleteMany) [`db.collection.deleteOne()`](https://docs.mongodb.com/manual/reference/method/db.collection.deleteOne/#db.collection.deleteOne) [`db.collection.remove()`](https://docs.mongodb.com/manual/reference/method/db.collection.remove/#db.collection.remove)                                                                                                                                                                                                                                           | ✓                                                                                                  |                                                                                                                |                                                                                                             | ✓                                                                                                           |                                                                                                                         |
| [`findAndModify`](https://docs.mongodb.com/manual/reference/command/findAndModify/#dbcmd.findAndModify) [`db.collection.findAndModify()`](https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/#db.collection.findAndModify) [`db.collection.findOneAndDelete()`](https://docs.mongodb.com/manual/reference/method/db.collection.findOneAndDelete/#db.collection.findOneAndDelete) [`db.collection.findOneAndReplace()`](https://docs.mongodb.com/manual/reference/method/db.collection.findOneAndReplace/#db.collection.findOneAndReplace) [`db.collection.findOneAndUpdate()`](https://docs.mongodb.com/manual/reference/method/db.collection.findOneAndUpdate/#db.collection.findOneAndUpdate) | ✓                                                                                                  |                                                                                                                |                                                                                                             | ✓                                                                                                           |                                                                                                                         |
| [`insert`](https://docs.mongodb.com/manual/reference/command/insert/#dbcmd.insert) [`db.collection.insert()`](https://docs.mongodb.com/manual/reference/method/db.collection.insert/#db.collection.insert) [`db.collection.insertOne()`](https://docs.mongodb.com/manual/reference/method/db.collection.insertOne/#db.collection.insertOne) [`db.collection.insertMany()`](https://docs.mongodb.com/manual/reference/method/db.collection.insertMany/#db.collection.insertMany)                                                                                                                                                                                                                                           | ✓                                                                                                  |                                                                                                                |                                                                                                             | ✓                                                                                                           |                                                                                                                         |
| [`update`](https://docs.mongodb.com/manual/reference/command/update/#dbcmd.update) [`db.collection.update()`](https://docs.mongodb.com/manual/reference/method/db.collection.update/#db.collection.update) [`db.collection.updateMany()`](https://docs.mongodb.com/manual/reference/method/db.collection.updateMany/#db.collection.updateMany) [`db.collection.updateOne()`](https://docs.mongodb.com/manual/reference/method/db.collection.updateOne/#db.collection.updateOne) [`db.collection.replaceOne()`](https://docs.mongodb.com/manual/reference/method/db.collection.replaceOne/#db.collection.replaceOne)                                                                                                       | ✓                                                                                                  |                                                                                                                |                                                                                                             | ✓                                                                                                           |                                                                                                                         |

|      |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| \[3] | *(*[*1*](https://docs.mongodb.com/manual/reference/read-concern/#id3)*,* [*2*](https://docs.mongodb.com/manual/reference/read-concern/#id7)\_)\_读关注[“SNAPSHOT”](https://docs.mongodb.com/manual/reference/read-concern-snapshot/#readconcern.%22snapshot)仅适用于多文档事务，并且对于事务，您可以在事务级别设置读关注。支持[“SNAPSHOT”](https://docs.mongodb.com/manual/reference/read-concern-snapshot/#readconcern.%22snapshot)的操作对应于事务中可用的CRUD操作。有关更多信息，请参见[事务和读关注](https://docs.mongodb.com/manual/core/transactions/#transactions-read-concern) |
|      |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |

## 注意事项

### 读自己的文章

在版本3.6中更改

从MongoDB 3.6版本开始，如果写请求确认，你可以使用[因果一致的会话](https://docs.mongodb.com/manual/core/read-isolation-consistency-recency/#sessions)读你自己写入的内容。

在MongoDB 3.6之前，您必须使用 `{ w: "majority" }` 写关注发出写操作，然后对读操作使用 [`"majority"`](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern.%22majority%22) 或者 [`"linearizable"`](https://docs.mongodb.com/manual/reference/read-concern-linearizable/#readconcern.%22linearizable%22)读关注，以确保单个线程可以读取自己的写入内容

### 实时顺序

结合[`"majority"`](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern.%22majority%22) 写关注，[`"linearizable"`](https://docs.mongodb.com/manual/reference/read-concern-linearizable/#readconcern.%22linearizable%22) 读关注使多个线程可以在单个文档上执行读写操作，就好像单个线程实时地执行了这些操作一样。 也就是说，这些读写的对应的计划被认为是线性的。

### 性能比较

与[`"majority"`](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern.%22majority%22)不同，[`"linearizable"`](https://docs.mongodb.com/manual/reference/read-concern-linearizable/#readconcern.%22linearizable%22) 的读关注通过从节点确认读操作正在从主节点读，该操作能够以[`{ w: "majority" }`](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern.%22majority%22)写关注来确认写入。 [\[4\]](https://docs.mongodb.com/manual/reference/read-concern/#edge-cases-2-primaries)因此，具有线性化读关注的读取可能比具有[`"majority"`](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern.%22majority%22) 或 [`"local"`](https://docs.mongodb.com/manual/reference/read-concern-local/#readconcern.%22local%22)读关注的读慢得多。

为了避免万一大多数数据承载成员不可用，请始终将 `maxTimeMS` 与可线性化的读确认一起使用。`maxTimeMS` 确保操作不会无限期地阻塞，而是确保如果无法满足读取要求，则操作将返回错误。

例如：

```
db.restaurants.find( { _id: 5 } ).readConcern("linearizable").maxTimeMS(10000)
db.runCommand( {
     find: "restaurants",
     filter: { _id: 5 },
     readConcern: { level: "linearizable" },
     maxTimeMS: 10000
} )
```

|                                                                      |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| -------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [\[4\]](https://docs.mongodb.com/manual/reference/read-concern/#id8) | 在[某些情况](https://docs.mongodb.com/manual/core/read-preference-use-cases/#edge-cases)下，副本集中的两个节点可能会短暂地认为它们是主节点，但至多，其中一个节点将能够以[`{ w: "majority" }`](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern.%22majority%22)写关注完成。 可以完成[`{ w: "majority" }`](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern.%22majority%22)写入的节点是当前主节点，另一个节点是前主节点，由于[网络分区](https://docs.mongodb.com/manual/reference/glossary/#term-network-partition)的原因，该主节点尚未意识到其降级。 发生这种情况时，尽管请求的读优先级为[主节点](https://docs.mongodb.com/manual/core/read-preference/#primary)，但连接到前主界定啊的客户端仍可能会读到过时的数据，并且最终将对前主节点新写入的进行回滚。 |
|                                                                      |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |

### 读操作和afterClusterTime

3.6 版本新加入

MongoDB 3.6引入了对[因果一致会话](https://docs.mongodb.com/manual/core/read-isolation-consistency-recency/#sessions)的支持。 对于与因果一致的会话相关联的读操作，MongoDB 3.6引入了 `afterClusterTime` 读关注选项，驱动程序会自动将`afterClusterTime` 读关注选项设置为与因果一致的会话相关联的操作。

> **\[warning] 重要**
>
> 不要手动为读操作设置 `afterClusterTime` 。 MongoDB驱动程序会针对与因果一致的会话相关联的操作自动设置此值。 但是，您可以提前会话的操作时间和群集时间，以便与另一个客户端会话的操作保持一致。 有关示例，请参见[示例](https://docs.mongodb.com/manual/core/read-isolation-consistency-recency/#causal-consistency-examples)。

为了满足 `afterClusterTime` 值为`T`的读请求， [`mongod`](https://docs.mongodb.com/manual/reference/program/mongod/#bin.mongod) 必须在其oplog到达时间`T`之后执行请求。如果其oplog尚未达到时间`T`，则 [`mongod`](https://docs.mongodb.com/manual/reference/program/mongod/#bin.mongod) 必须等待服务该请求。

使用指定的 `afterClusterTime` 的读操作将返回满足读关注级别要求和指定的 `afterClusterTime` 要求的数据。

对于与因果一致会话无关的读操作，未设置 `afterClusterTime`。

#### 阅读问题出处

从4.4版本开始，MongoDB跟踪阅读关注来源，表示某个特定读取关注点的来源。您可能会在[`getLastError`](https://docs.mongodb.com/master/reference/command/serverStatus/#serverstatus.metrics.getLastError)指标、读取关注错误对象和MongoDB日志中看到出处。

下表显示了可能的阅读问题**provenance**值及其重要性:

| 出处                | 描述                                                                                                                                            |
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `clientSupplied`  | read关注点是在应用程序中指定的。                                                                                                                            |
| `customDefault`   | 读取关注点源自自定义的默认值。 参见 [`setDefaultRWConcern`](https://docs.mongodb.com/master/reference/command/setDefaultRWConcern/#dbcmd.setDefaultRWConcern). |
| `implicitDefault` | 在没有其他所有读取关注规范的情况下，读取关注源自服务器。                                                                                                                  |

译者：杨帅 张琦

校对：杨帅


# 读关注 "local"

具有读取关注点的查询`local`从实例返回数据，但不保证数据已写入大多数复制集成员(即：可能会回滚)。

读取关注`local`是默认值：

* 读取针对主要的操作
* 如果读取与因果关系一致关联，则读取针对辅助节点的操作。

不管[读关注](https://docs.mongodb.com/manual/reference/glossary/#term-read-concern)级别如何，节点上的最新数据都可能无法反映系统中数据的最新版本。

## 可用性

读关注`local`可用于有或没有因果关系一致的会话和事务。

## 读关注”local“和事务

您可以在事务级别上而不是在单个操作级别上设置读取关注。要设置事务的已读关注点，请参见[事务和已读关注点](https://docs.mongodb.com/manual/core/transactions/#transactions-read-concern)。

从MongoDB 4.4开始，[功能兼容版本(fcv)](https://docs.mongodb.com/master/reference/command/setFeatureCompatibilityVersion/#view-fcv) “4.4”或更高版本，您可以在事务中创建集合和索引。如果显式地创建集合或索引，则事务必须使用read concern“\[`"local"`]\([https://docs.mongodb.com/master/reference/read-concern-local/#readconcern."local")。\[隐式\](https://docs.mongodb.com/master/core/transactions-operations/#transactions-operations-ddl-implicit)创建集合可以使用事务可用的任何读取关注点。](https://docs.mongodb.com/master/reference/read-concern-local/#readconcern."local"%29。\[隐式]%28https://docs.mongodb.com/master/core/transactions-operations/#transactions-operations-ddl-implicit%29创建集合可以使用事务可用的任何读取关注点。)

## 例子

考虑写入操作 Write0 到三个成员副本集的以下时间轴：

> **注意**
>
> * Write0 之前的所有写操作都已成功复制到所有成员。
> * Writeprev 是 Write0之前的写入。
> * 在 Write0之后没有发生其他写操作。

![对三个成员复制集的写操作的时间轴。](https://docs.mongodb.com/manual/_images/read-concern-write-timeline.svg)

| 时间 | 事件                                         | 最新写                                   | 最新的多数写                                   |
| -- | ------------------------------------------ | ------------------------------------- | ---------------------------------------- |
| t0 | 主要适用于Write0                                | 主要：Write0 次要1：Writeprev 次要2：Writeprev | 主要：Writeprev 次要1：Writeprev 次要2：Writeprev |
| t1 | Secondary1适用于Write0                        | 主要：Write0 次要1：Write0 次要2：Writeprev    | 主要：Writeprev 次要1：Writeprev 次要2：Writeprev |
| t2 | Secondary2适用于Write0                        | 主要：Write0 次要1：Write0 次要2：Write0       | 主要：Writeprev 次要1：Writeprev 次要2：Writeprev |
| t3 | Primary知道到Secondary1的复制成功，并向客户端发送确认        | 主要：Write0 次要1：Write0 次要2：Write0       | 主要：Write0 次要1：Writeprev 次要2：Writeprev    |
| t4 | Primary 知道成功复制到 Secondary2                 | 主要：Write0 次要1：Write0 次要2：Write0       | 主要：Write0 次要1：Writeprev 次要2：Writeprev    |
| t5 | Secondary1接收通知(通过常规复制机制)以更新其最近 w：“多数”写入的快照 | 主要：Write0 次要1：Write0 次要2：Write0       | 主要：Write0 次要1：Write0 次要2：Writeprev       |
| t6 | Secondary2接收通知(通过常规复制机制)以更新其最近 w：“多数”写入的快照 | 主要：Write0 次要1：Write0 次要2：Write0       | 主要：Write0 次要1：Write0 次要2：Write0          |

然后，下表总结了具有[“local”](/mongodb-crud-operations/read-isolation-read-concern/read-concern-local)读关注的读操作在T时刻看到的数据状态。

![Timeline of a write operation to a three member replica set.](https://docs.mongodb.com/manual/_images/read-concern-write-timeline.svg)

|            |          |                 |
| ---------- | -------- | --------------- |
| 阅读目标       | Time `T` | 数据状态            |
| Primary    | 在t0之后    | 数据反映了 Write0    |
| Secondary1 | 在t1之前    | 数据反映了 Writeprev |
| Secondary1 | 在t1之后    | 数据反映了 Write0    |
| Secondary2 | 在t2之前    | 数据反映了 Writeprev |
| Secondary2 | 在t2之后    | 数据反映了 Write0    |

译者：杨帅

校对：杨帅


# 读关注 "available"

version 3.6 中的新内容。

与read有关的“available”查询从实例返回数据，但不保证数据已经被写入大多数复制集成员(即可能被回滚)。

如果读操作不与因果一致的会话相关联，那么读关注“available”是对次要操作的默认读操作。

**对于分片 cluster**，\[`"available"`]\(<https://docs.mongodb.com/master/reference/read-concern-available/#readconcern."available>") 读取问题为分区提供了更大的容忍度，因为它不会等待以确保一致性保证。但是，如果分片正在进行大块迁移，那么带有 \[`"available"`]\([https://docs.mongodb.com/master/reference/read-concern-available/#readconcern."available")读取问题的查询可能会return孤立文档，因为“本地”读取问题与“本地”读取问题不同，它不会联系分片的主服务器或配置服务器以更新元数据。](https://docs.mongodb.com/master/reference/read-concern-available/#readconcern."available"%29读取问题的查询可能会return孤立文档，因为“本地”读取问题与“本地”读取问题不同，它不会联系分片的主服务器或配置服务器以更新元数据。)

**对于unsharded集合**(包括独立部署或复制集部署中的集合)，\[`"local"`]\(<https://docs.mongodb.com/master/reference/read-concern-local/#readconcern."local>") 和 \[`"available"`]\(<https://docs.mongodb.com/master/reference/read-concern-available/#readconcern."available>") 读取问题的行为相同。

不管[read concern](https://docs.mongodb.com/master/reference/glossary/#term-read-concern)级别，节点上的最新数据可能不能反映系统中数据的最新版本。

> **也可以看看**
>
> [`orphanCleanupDelaySecs`](https://docs.mongodb.com/master/reference/parameters/#param.orphanCleanupDelaySecs)

## 可用行

读关注 **available**对于因果一致的会话和事务不可用。

## 例子

考虑写入操作 Write0 到三个成员复制集的以下时间轴：

> **\[success] Note**
>
> 为了简化，本例假设:
>
> * Write0 之前的所有写操作都已成功复制到所有成员。
> * Writeprev 是 Write0之前的写入。
> * 在 Write0之后没有发生其他写操作。

![Timeline of a write operation to a three member replica set.](https://docs.mongodb.com/manual/_images/read-concern-write-timeline.svg)

| 时间 | 事件                                         | 最新写                                   | 最新的多数写                                   |
| -- | ------------------------------------------ | ------------------------------------- | ---------------------------------------- |
| t0 | 主要适用于Write0                                | 主要：Write0 次要1：Writeprev 次要2：Writeprev | 主要：Writeprev 次要1：Writeprev 次要2：Writeprev |
| t1 | Secondary1适用于Write0                        | 主要：Write0 次要1：Write0 次要2：Writeprev    | 主要：Writeprev 次要1：Writeprev 次要2：Writeprev |
| t2 | Secondary2适用于Write0                        | 主要：Write0 次要1：Write0 次要2：Write0       | 主要：Writeprev 次要1：Writeprev 次要2：Writeprev |
| t3 | Primary知道到Secondary1的复制成功，并向客户端发送确认        | 主要：Write0 次要1：Write0 次要2：Write0       | 主要：Write0 次要1：Writeprev 次要2：Writeprev    |
| t4 | Primary 知道成功复制到 Secondary2                 | 主要：Write0 次要1：Write0 次要2：Write0       | 主要：Write0 次要1：Writeprev 次要2：Writeprev    |
| t5 | Secondary1接收通知(通过常规复制机制)以更新其最近 w：“多数”写入的快照 | 主要：Write0 次要1：Write0 次要2：Write0       | 主要：Write0 次要1：Write0 次要2：Writeprev       |
| t6 | Secondary2接收通知(通过常规复制机制)以更新其最近 w：“多数”写入的快照 | 主要：Write0 次要1：Write0 次要2：Write0       | 主要：Write0 次要1：Write0 次要2：Write0          |

然后，下表总结了 time读取关注的读操作在 time `T`处将看到的数据的 state。

|            |           |                         |
| ---------- | --------- | ----------------------- |
| 阅读目标       | Time `T`  | 状态的数据                   |
| Primary    | After t0  | Data reflects Write0    |
| Secondary1 | Before t1 | Data reflects Writeprev |
| Secondary1 | After t1  | Data reflects Write0    |
| Secondary2 | Before t2 | Data reflects Writeprev |
| Secondary2 | After t2  | Data reflects Write0    |

译者：杨帅

校对：杨帅


# 读关注 "majority"

**在本页面**

* [性能](#性能)
* [可用性](#可用性)
* [例子](#例子)
* [存储引擎支持](#支持)
* [读关注`"majority"`和事务](#事务)
* [读关注`"majority"`和汇总](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/MongoDB-CRUD-Operations/Read-Isolation-Read-Concern/总/README.md)
* [读取自己的写入](#写入)
* [禁用读关注多数](#禁用)

对于[多文档事务](https://docs.mongodb.com/master/core/transactions/)中无关的读操作，阅读问题\*\*“majority”\*\*保证所读的数据得到了大多数复制集成员的认可(即，所读的文档是持久的，并且保证不会回滚)。

对于[多文档事务](https://docs.mongodb.com/master/core/transactions/)中的操作，只有当事务以写关注点“多数”提交时，读关注点\[`多数`]\([https://docs.mongodb.com/master/reference/read-concern-majority/#readconcern."majority")才提供保证。否则，“多数”读取关注不能保证在事务中读取的数据。](https://docs.mongodb.com/master/reference/read-concern-majority/#readconcern."majority"%29才提供保证。否则，“多数”读取关注不能保证在事务中读取的数据。)

不管读关注级别是什么，节点上的最新数据都可能不能反映系统中数据的最新版本。

## 性能

每个复制集成员在内存中维护多数提交点处的数据视图。多数提交点是由初级计算的。为了满足读取关注\*\*"majority"\*\*，该节点从该视图返回数据，并且性能成本与其他读取关注相当。

## 可用性

无论会话和事务是否一致，都可以使用读关注\[`"majority"`]\([https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")。](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29。)

对于使用三成员`主-副-仲裁(PSA)`体系结构的部署，可以禁用读关注 \[`"majority"`]\([https://docs.mongodb.com/master/reference/read-concern-majority/#readconcern."majority")”,然而，这对更改流(MongoDB](https://docs.mongodb.com/master/reference/read-concern-majority/#readconcern."majority"%29”,然而，这对更改流%28MongoDB) 4.0和更早版本中只使用)和分片集群上的事务有影响。有关更多信息，请参见[禁用读关注多数](https://docs.mongodb.com/master/reference/read-concern-majority/#disable-read-concern-majority).。

## 例子

考虑写入操作 Write0 到三个成员复制集的以下时间轴：

> **注意**
>
> * Write0 之前的所有写操作都已成功复制到所有成员。
> * Writeprev 是 Write0之前的写入。
> * 在 Write0之后没有发生其他写操作。

![Timeline of a write operation to a three member replica set.](https://docs.mongodb.com/manual/_images/read-concern-write-timeline.svg)

| 时间 | 事件                                         | 最新写                                   | 最新的多数写                                   |
| -- | ------------------------------------------ | ------------------------------------- | ---------------------------------------- |
| t0 | 主要适用于Write0                                | 主要：Write0 次要1：Writeprev 次要2：Writeprev | 主要：Writeprev 次要1：Writeprev 次要2：Writeprev |
| t1 | Secondary1适用于Write0                        | 主要：Write0 次要1：Write0 次要2：Writeprev    | 主要：Writeprev 次要1：Writeprev 次要2：Writeprev |
| t2 | Secondary2适用于Write0                        | 主要：Write0 次要1：Write0 次要2：Write0       | 主要：Writeprev 次要1：Writeprev 次要2：Writeprev |
| t3 | Primary知道到Secondary1的复制成功，并向客户端发送确认        | 主要：Write0 次要1：Write0 次要2：Write0       | 主要：Write0 次要1：Writeprev 次要2：Writeprev    |
| t4 | Primary 知道成功复制到 Secondary2                 | 主要：Write0 次要1：Write0 次要2：Write0       | 主要：Write0 次要1：Writeprev 次要2：Writeprev    |
| t5 | Secondary1接收通知(通过常规复制机制)以更新其最近 w：“多数”写入的快照 | 主要：Write0 次要1：Write0 次要2：Write0       | 主要：Write0 次要1：Write0 次要2：Writeprev       |
| t6 | Secondary2接收通知(通过常规复制机制)以更新其最近 w：“多数”写入的快照 | 主要：Write0 次要1：Write0 次要2：Write0       | 主要：Write0 次要1：Write0 次要2：Write0          |

然后，下表总结了具有\[`"majority"`]\([https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")读关注的读取操作在时间将看到的数据状态\`T\`。](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29读关注的读取操作在时间将看到的数据状态`T`。)

![Timeline of a write operation to a three member replica set.](https://docs.mongodb.com/manual/_images/read-concern-write-timeline.svg)

|            |          |                 |
| ---------- | -------- | --------------- |
| 阅读目标       | Time `T` | 数据状态            |
| Primary    | 在t3之前    | 数据反映了 Writeprev |
| Primary    | 在t3之后    | 数据反映了 Write0    |
| Secondary1 | 在t5之前    | 数据反映了 Writeprev |
| Secondary1 | 在t5之后    | 数据反映了 Write0    |
| Secondary2 | 在t6之前    | 数据反映了 Writeprev |
| Secondary2 | 在t6之后    | 数据反映了 Write0    |

## 存储引擎支持

阅读关注“多数”是可用的WiredTiger存储引擎。

> **提示**
>
> [serverStatus](/mongodb-crud-operations/read-isolation-read-concern/read-concern-majority)命令返回[storageEngine.supportsCommittedReads](/mongodb-crud-operations/read-isolation-read-concern/read-concern-majority)字段，该字段指示存储引擎是否支持\*\*”majority“\*\*读取问题。

## 读关注`"majority"`和事务

> **\[success] Note**
>
> 您可以在事务级别上而不是在单个操作级别上设置读关注。要设置事务的已读关注点，请参见[事务和已读关注点](https://docs.mongodb.com/manual/core/transactions/#transactions-read-concern)。

对于[多文档事务中的操作](https://docs.mongodb.com/manual/core/transactions/)，`"majority"`仅当事务以[写关注“多数”](https://docs.mongodb.com/manual/core/transactions/#transactions-write-concern)提交时，读关注才提供其保证。否则， \[`"majority"`]\([https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")读取关注点不能保证事务中读取的数据。](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29读取关注点不能保证事务中读取的数据。)

## 读关注`"majority"`和汇总

从MongoDB 4.2开始，您可以为包含[`$out`](https://docs.mongodb.com/manual/reference/operator/aggregation/out/#pipe._S_out)阶段的聚合指定[读取关注](https://docs.mongodb.com/manual/reference/read-concern/) level \[`"majority"`]\([https://docs.mongodb.com/master/reference/read-concern-majority/#readconcern."majority")。](https://docs.mongodb.com/master/reference/read-concern-majority/#readconcern."majority"%29。)

在MongoDB 4.0和更早版本中，您不能包括将读取关注用于聚合的[`$out`](https://docs.mongodb.com/manual/reference/operator/aggregation/out/#pipe._S_out) 阶段\[`"majority"`]\([https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")。](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29。)

## 读取自己的写入

更改了 version 3.6.

从 MongoDB 3.6 开始，如果写请求确认，则可以使用因果关系一致来读取您自己的写入。

在MongoDB 3.6之前，您必须发出具有写入关注点的写入操作， 然后 对读取操作使用或关注读取，以确保单个线程可以读取自己的写入。\[`{ w: "majority" }`]\([https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority")\[\`"majority"\`\](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")\[\`"linearizable"\`\](https://docs.mongodb.com/manual/reference/read-concern-linearizable/#readconcern."linearizable](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority"%29\[`"majority"`]%28https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29\[`"linearizable"`]%28https://docs.mongodb.com/manual/reference/read-concern-linearizable/#readconcern."linearizable)").

在MongoDB 3.6之前，你必须使用\[`{ w: "majority" }`]\(<https://docs.mongodb.com/master/reference/write-concern/#writeconcern."majority>") 写关注点来发布写操作，然后使用\[`"majority"`]\([https://docs.mongodb.com/master/reference/read-concern-majority/#readconcern."majority")或\[\`"linearizable"\`\](https://docs.mongodb.com/master/reference/read-concern-linearizable/#readconcern."linearizable](https://docs.mongodb.com/master/reference/read-concern-majority/#readconcern."majority"%29或\[`"linearizable"`]%28https://docs.mongodb.com/master/reference/read-concern-linearizable/#readconcern."linearizable)") 的读关注点来执行读操作，以确保单个线程可以读取自己的写操作。

## 禁用读关注多数

适用于3成员`主-副-仲裁器`体系结构

\[`"majority"`]\([https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")如果您具有具有主要-次要仲裁器（PSA）体系结构的三成员复制集或具有三成员PSA分片的分片群集，则可以禁用读关注。](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29如果您具有具有主要-次要仲裁器（PSA）体系结构的三成员复制集或具有三成员PSA分片的分片群集，则可以禁用读关注。)

> **\[success] Note**
>
> 如果您使用的是 3-member PSA 以外的部署，则无需禁用多数读关注。

对于三成员PSA架构，缓存压力将增加，如果任何承载数据的节点是关闭的。为了防止存储缓存压力使PSA架构的部署无法被锁定，您可以通过设置以下任一项来禁用read concern:

* [`--enableMajorityReadConcern`](https://docs.mongodb.com/manual/reference/program/mongod/#cmdoption-mongod-enablemajorityreadconcern)的命令行选项`false`。
* [`replication.enableMajorityReadConcern`](https://docs.mongodb.com/manual/reference/configuration-options/#replication.enableMajorityReadConcern)配置文件设置为`false`。

要检查是否已禁用“大多数”的读关注，您可以[`db.serverStatus()`](https://docs.mongodb.com/manual/reference/method/db.serverStatus/#db.serverStatus)在[`mongod`](https://docs.mongodb.com/manual/reference/program/mongod/#bin.mongod)实例上运行 并检查该[`storageEngine.supportsCommittedReads`](https://docs.mongodb.com/manual/reference/command/serverStatus/#serverstatus.storageEngine.supportsCommittedReads)字段。如果为`false`，则禁用“大多数”关注。

> **\[warning] 重要**
>
> 通常，除非必要，否则请避免禁用\[`"majority"`]\(<https://docs.mongodb.com/master/reference/read-concern-majority/#readconcern."majority>") 读取问题。但是，如果您的 three-member 复制集具有 `主-副-仲裁(PSA)`体系结构 或带有 three-member PSA 分片的分片 cluster，请禁用以防止存储缓存压力导致部署无法运行。 禁用“多数”读取问题会禁用对改变流的支持。

**变更流**

禁用\[`"majority"`]\([https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")读取关注会禁用对MongoDB](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29读取关注会禁用对MongoDB) 4.0及更早版本的[变更流的](https://docs.mongodb.com/manual/changeStreams/)支持。对于MongoDB 4.2+，禁用读取关注\*\*"majority"\*\*不会影响变更流的可用性。

**事务次数**

禁用\[`"majority"`]\([https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")读取关注会影响对分片群集上\[事务的\](https://docs.mongodb.com/manual/core/transactions/)支持](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29读取关注会影响对分片群集上\[事务的]%28https://docs.mongodb.com/manual/core/transactions/%29支持) 。特别：

* \[`"snapshot"`]\([https://docs.mongodb.com/manual/reference/read-concern-snapshot/#readconcern."snapshot")如果事务涉及已\[禁用读取关注“多数”的分片\](https://docs.mongodb.com/manual/reference/read-concern-majority/#disable-read-concern-majority)，则该事务不能使用读取关注。](https://docs.mongodb.com/manual/reference/read-concern-snapshot/#readconcern."snapshot"%29如果事务涉及已\[禁用读取关注“多数”的分片]%28https://docs.mongodb.com/manual/reference/read-concern-majority/#disable-read-concern-majority%29，则该事务不能使用读取关注。)
* 如果事务的任何读或写操作写入多个分片错误，则该事务涉及已禁用读取关注的分片\[`"majority"`]\([https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")。](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29。)

但是，它不影响复制集上的[事务](https://docs.mongodb.com/manual/core/transactions/)。对于复制集上的事务，即使禁用了读关注，也可以为多文档事务指定读关注\[`"majority"`]\([https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")（或\[\`"snapshot"\`\](https://docs.mongodb.com/manual/reference/read-concern-snapshot/#readconcern."snapshot](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29（或\[`"snapshot"`]%28https://docs.mongodb.com/manual/reference/read-concern-snapshot/#readconcern."snapshot)") 或\[`"local"`]\([https://docs.mongodb.com/manual/reference/read-concern-local/#readconcern."local")）\[\`"majority"\`\](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")。](https://docs.mongodb.com/manual/reference/read-concern-local/#readconcern."local"%29）\[`"majority"`]%28https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29。)

**回滚的注意事项**

禁用\[`"majority"`]\([https://docs.mongodb.com/master/reference/read-concern-majority/#readconcern."majority")读关注可以防止修改索引的\[\`collMod\`\](https://docs.mongodb.com/master/reference/command/collMod/#dbcmd.collMod](https://docs.mongodb.com/master/reference/read-concern-majority/#readconcern."majority"%29读关注可以防止修改索引的\[`collMod`]%28https://docs.mongodb.com/master/reference/command/collMod/#dbcmd.collMod)) 命令回滚。如果需要[回滚](https://docs.mongodb.com/master/core/replica-set-rollbacks/#replica-set-rollbacks)此类操作，则必须将受影响的节点与主节点重新同步。


# 读关注 "linearizable"

3.4版本中的新功能。

该查询返回的数据反映了在开始读操作之前完成的所有成功的经过多数确认的写操作。在返回结果之前，查询可以等待并发执行的写传播到大多数复制集成员。

如果大多数复制集成员在读取操作后崩溃并重新启动，则如果[`writeConcernMajorityJournalDefault`](https://docs.mongodb.com/master/reference/replica-configuration/#rsconf.writeConcernMajorityJournalDefault)设置为`true`的默认 state，则读取操作返回的文档是持久的。

当[`writeConcernMajorityJournalDefault`](https://docs.mongodb.com/master/reference/replica-configuration/#rsconf.writeConcernMajorityJournalDefault)设置为`false`时，MongoDB 不会等待 \[`w: "majority"`]\([https://docs.mongodb.com/master/reference/write-concern/#writeconcern."majority")写入在确认写入之前写入磁盘上日志。因此，\`majority\`写操作可能会在给定复制集中的大多数节点的瞬时丢失(即](https://docs.mongodb.com/master/reference/write-concern/#writeconcern."majority"%29写入在确认写入之前写入磁盘上日志。因此，`majority`写操作可能会在给定复制集中的大多数节点的瞬时丢失%28即). 崩溃和重启)的事件中回滚。

您可以仅为主节点上的读操作指定可线性化的读关注。

可线性化读取关注保证仅在读取操作指定唯一标识单个文档的查询过滤器时才适用。

> **提示**
>
> 如果大多数数据承载成员不可用，请始终使用带有线性化读取问题的`maxTimeMS`。 `maxTimeMS`确保操作不会无限期地阻塞，而是确保在无法满足读取关注时操作返回错误。

## 因果一致的会话

对于因果一致会话，读关注**linearizable**不可用。

## 聚集限制

不能将[`$out`](https://docs.mongodb.com/master/reference/operator/aggregation/out/#pipe._S_out) 或 [`$merge`](https://docs.mongodb.com/master/reference/operator/aggregation/merge/#pipe._S_merge) 阶段与read关注点\[`线性化`]\([https://docs.mongodb.com/master/reference/read-concern-linearizable/#readconcern."linearizable")结合使用。也就是说，如果您为\[\`db.collection.aggregate()\`\](https://docs.mongodb.com/master/reference/method/db.collection.aggregate/#db.collection.aggregate)指定了\[\`"linearizable"\`\](https://docs.mongodb.com/master/reference/read-concern-linearizable/#readconcern."linearizable")读关注，则不能在管道中包含这两个阶段。](https://docs.mongodb.com/master/reference/read-concern-linearizable/#readconcern."linearizable"%29结合使用。也就是说，如果您为\[`db.collection.aggregate%28%29`]%28https://docs.mongodb.com/master/reference/method/db.collection.aggregate/#db.collection.aggregate%29指定了\[`"linearizable"`]%28https://docs.mongodb.com/master/reference/read-concern-linearizable/#readconcern."linearizable"%29读关注，则不能在管道中包含这两个阶段。)

## 实时订单

结合\[`"majority"`]\([https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority")写关注，](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority"%29写关注，) \[`"linearizable"`]\([https://docs.mongodb.com/manual/reference/read-concern-linearizable/#readconcern."linearizable")读关注使多个线程可以在单个文档上执行读写操作，就好像单个线程实时执行了这些操作一样。也就是说，这些读写的相应计划被认为是线性的。](https://docs.mongodb.com/manual/reference/read-concern-linearizable/#readconcern."linearizable"%29读关注使多个线程可以在单个文档上执行读写操作，就好像单个线程实时执行了这些操作一样。也就是说，这些读写的相应计划被认为是线性的。)

## 读取自己的写入

更改了3.6版本.

从 MongoDB 3.6 开始，如果写请求确认，则可以使用 [因果关系一致](https://docs.mongodb.com/master/core/read-isolation-consistency-recency/#sessions)来读取您自己的写入。

在MongoDB 3.6之前，你必须使用 \[`{ w: "majority" }`]\(<https://docs.mongodb.com/master/reference/write-concern/#writeconcern."majority>") 写关注点来发布写操作，然后使用\[`"majority"`]\(<https://docs.mongodb.com/master/reference/read-concern-majority/#readconcern."majority>") 或\[`"linearizable"`]\(<https://docs.mongodb.com/master/reference/read-concern-linearizable/#readconcern."linearizable>") 的读关注点来执行读操作，以确保单个线程可以读取自己的写操作。

## 性能比较

与“多数”不同，“可线性化”的读关注点向辅助成员确认读操作是从能够用 \[`{ w: "majority" }`]\(<https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority>") 写关注点确认写操作的主成员读取的。这样，线性化的读取可能比“多数”或“局部”读取要慢得多。

与\[`"majority"`]\([https://docs.mongodb.com/master/reference/read-concern-majority/#readconcern."majority")不同，\[\`"linearizable"\`\](https://docs.mongodb.com/master/reference/read-concern-linearizable/#readconcern."linearizable")的读关注点向辅助成员确认读操作是从能够用](https://docs.mongodb.com/master/reference/read-concern-majority/#readconcern."majority"%29不同，\[`"linearizable"`]%28https://docs.mongodb.com/master/reference/read-concern-linearizable/#readconcern."linearizable"%29的读关注点向辅助成员确认读操作是从能够用) \[`{ w: "majority" }`]\([https://docs.mongodb.com/master/reference/write-concern/#writeconcern."majority")写关注点确认写操作的主成员读取的。\[\[1\]\](https://docs.mongodb.com/master/reference/read-concern-linearizable/#edge-cases-2-primaries](https://docs.mongodb.com/master/reference/write-concern/#writeconcern."majority"%29写关注点确认写操作的主成员读取的。\[\[1]]%28https://docs.mongodb.com/master/reference/read-concern-linearizable/#edge-cases-2-primaries)) 这样，线性化的读取可能比 \[`"majority"`]\(<https://docs.mongodb.com/master/reference/read-concern-majority/#readconcern."majority>") 或 \[`"local"`]\([https://docs.mongodb.com/master/reference/read-concern-local/#readconcern."local")读取要慢得多。](https://docs.mongodb.com/master/reference/read-concern-local/#readconcern."local"%29读取要慢得多。)

总是使用可线性化读取关注的maxTimeMS，以防大多数数据承载成员不可用。maxTimeMS确保了操作不会无限期地阻塞，相反，它确保了如果读问题不能实现，操作会返回一个错误。

例如：

```
db.restaurants.find( { _id: 5 } ).readConcern("linearizable").maxTimeMS(10000)

db.runCommand( {
     find: "restaurants",
     filter: { _id: 5 },
     readConcern: { level: "linearizable" },
     maxTimeMS: 10000
} )
```

[\[1\]](https://docs.mongodb.com/master/reference/read-concern-linearizable/#id1) 在某些情况下，一个复制集中的两个节点可能暂时认为它们是主节点，但它们中的一个最多能够完成\[`{ w: "majority" }`]\([https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority")写关注点的写操作。能够完成\[\`{](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority"%29写关注点的写操作。能够完成\[`{) w: "majority" }\`]\([https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority")写操作的节点是当前主节点，而另一个节点是前主节点，它还没有意识到降级，通常是由于网络分区。当发生这种情况时，连接到前主服务器的客户机可能会观察到陈旧的数据，尽管已经请求了读首选项主服务器，并且对前主服务器的新写操作最终将回滚。](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority"%29写操作的节点是当前主节点，而另一个节点是前主节点，它还没有意识到降级，通常是由于网络分区。当发生这种情况时，连接到前主服务器的客户机可能会观察到陈旧的数据，尽管已经请求了读首选项主服务器，并且对前主服务器的新写操作最终将回滚。)

译者：杨帅

校对：杨帅


# 读关注 "snapshot"

版本4.0中的新功能

读取关注\*\*“snapshot”\*\*只对多文档事务可用。

* 如果事务不是[因果一致会话](https://docs.mongodb.com/master/core/read-isolation-consistency-recency/#sessions)的一部分，那么在事务提交时，写关注点为\[`"majority"`]\([https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority")，事务操作就保证已经从多数提交数据的快照中读取了数据。](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority"%29，事务操作就保证已经从多数提交数据的快照中读取了数据。)
* 如果事务是[因果一致会话](https://docs.mongodb.com/master/core/read-isolation-consistency-recency/#sessions)的一部分，那么在事务提交时，write concern为\[`"majority"`]\([https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority")，事务操作保证已经从多数提交数据的快照中读取，该快照提供了与事务开始前的操作因果一致的数据。](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority"%29，事务操作保证已经从多数提交数据的快照中读取，该快照提供了与事务开始前的操作因果一致的数据。)

## 操作

有关接受阅读关注的所有操作的列表，请参阅 [支持读关注的操作](https://docs.mongodb.com/manual/reference/read-concern/#read-concern-operations)。

## 阅读关注和事务

多文档事务支持阅读关注 \[`"snapshot"`]\([https://docs.mongodb.com/manual/reference/read-concern-snapshot/#readconcern."snapshot")以及\[\`"local"\`\](https://docs.mongodb.com/manual/reference/read-concern-local/#readconcern."local")和](https://docs.mongodb.com/manual/reference/read-concern-snapshot/#readconcern."snapshot"%29以及\[`"local"`]%28https://docs.mongodb.com/manual/reference/read-concern-local/#readconcern."local"%29和) \[`"majority"`]\([https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")。](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29。)

> **\[success] Note**
>
> 您可以在事务级别上而不是在单个操作级别上设置读取关注。要设置事务的已读关注点，请参见[事务和已读关注点](https://docs.mongodb.com/manual/core/transactions/#transactions-read-concern)。

对于分片群集上的事务，如果事务中的任何操作涉及已[禁用读关注度“多数”的分片](https://docs.mongodb.com/manual/reference/read-concern-majority/#disable-read-concern-majority)，则不能\[`"snapshot"`]\([https://docs.mongodb.com/manual/reference/read-concern-snapshot/#readconcern."snapshot")对事务使用读关注度。您只能使用已读关注\[\`"local"\`\](https://docs.mongodb.com/manual/reference/read-concern-local/#readconcern."local")或\[\`"majority"\`\](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")用于事务。如果使用读取关注\[\`"snapshot"\`\](https://docs.mongodb.com/manual/reference/read-concern-snapshot/#readconcern."snapshot")，则事务错误并中止。有关更多信息，请参见](https://docs.mongodb.com/manual/reference/read-concern-snapshot/#readconcern."snapshot"%29对事务使用读关注度。您只能使用已读关注\[`"local"`]%28https://docs.mongodb.com/manual/reference/read-concern-local/#readconcern."local"%29或\[`"majority"`]%28https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29用于事务。如果使用读取关注\[`"snapshot"`]%28https://docs.mongodb.com/manual/reference/read-concern-snapshot/#readconcern."snapshot"%29，则事务错误并中止。有关更多信息，请参见) [禁用阅读关注多数](https://docs.mongodb.com/manual/core/transactions/#transactions-disabled-rc-majority)。

译者：杨帅

校对：杨帅


# Write Concern写关注

**在本页面**

* [编写关注规范](#规范)
* [确认行为](#行为)
* [因果一致的会话和写问题](#问题)
* [计算关注的多数](#多数)

写关注描述了MongoDB请求对独立[`mongod`](https://docs.mongodb.com/manual/reference/program/mongod/#bin.mongod)或[复制集](https://docs.mongodb.com/manual/replication/)或分片[群集](https://docs.mongodb.com/manual/sharding/)进行写操作的确认级别。在分片群集中，[`mongos`](https://docs.mongodb.com/manual/reference/program/mongos/#bin.mongos)实例会将写关注事项传递给分片。

> **\[success] Note**
>
> 对于[多文档事务](https://docs.mongodb.com/manual/core/transactions/)，可以在事务级别**而不是在单个操作级别**设置写关注。不要为事务中的各个写操作显式设置写关注点。

## 编写关注规范

写关注可包括以下字段：

```
{  w ： < value > ， j ： < boolean > ， wtimeout ： < number >  }
```

* 使用[w](https://docs.mongodb.com/manual/reference/write-concern/#wc-w)选项来请求确认写入操作已传播到指定数量的[`mongod`](https://docs.mongodb.com/manual/reference/program/mongod/#bin.mongod) 实例或[`mongod`](https://docs.mongodb.com/manual/reference/program/mongod/#bin.mongod)具有指定标签的实例。
* 该[j](https://docs.mongodb.com/manual/reference/write-concern/#wc-j)选项要求确认写操作已被写入到磁盘上的杂志，和
* 该[wtimeout](https://docs.mongodb.com/manual/reference/write-concern/#wc-wtimeout)选项来指定一个时间限制，以防止无限期阻塞写操作。

### w 选项

`w`选项请求确认写操作已传播到指定数量的mongod实例或具有指定标记的mongod实例。

使用`w`选项，可以使用以下\*\*w:<`value`>\*\*写入问题：

| 值                             | 描述                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `<number>`                    | 请求确认写操作已传播到指定数量的[`mongod`](https://docs.mongodb.com/manual/reference/program/mongod/#bin.mongod)实例。例如：`w: 1`请求确认写入操作已传播到[`mongod`](https://docs.mongodb.com/manual/reference/program/mongod/#bin.mongod)复制集中的独立副本或主副本。是MongoDB的默认写关注点。 如果在写操作已复制到任何辅助数据库之前主数据库已降级，则可以[回滚](https://docs.mongodb.com/manual/core/replica-set-rollbacks/#rollback-avoid)数据。`w: 1``w: 0`不要求确认写入操作。但是，可能会将有关套接字异常和网络错误的信息返回给应用程序。如果在写操作已复制到任何辅助数据库之前主数据库已降级，则可以[回滚](https://docs.mongodb.com/manual/core/replica-set-rollbacks/#rollback-avoid)数据 。`w: 0`如果指定但包括[j：true](https://docs.mongodb.com/manual/reference/write-concern/#wc-j)，则优先使用 [j：true](https://docs.mongodb.com/manual/reference/write-concern/#wc-j)来请求独立或复制集主副本的确认。`w: 0`[`mongod`](https://docs.mongodb.com/manual/reference/program/mongod/#bin.mongod)`w`大于1则需要来自主数据库的确认以及满足指定写入问题所需的尽可能多的数据承载辅助数据库的确认。例如，考虑一个具有一个主要成员和两个次要成员的3成员复制集。指定将需要主数据库和辅助数据库之一的确认。指定将需要主要和次要确认。`w: 2``w: 3`注意[Hidden](https://docs.mongodb.com/manual/core/replica-set-hidden-member/#replica-set-hidden-members)， [delayed](https://docs.mongodb.com/manual/core/replica-set-delayed-member/#replica-set-delayed-members)和[ priority 0](https://docs.mongodb.com/manual/core/replica-set-priority-0-member/#replica-set-secondary-only-members) 成员可以确认写操作。[`w:`](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern.)延迟的辅助副本可以在不早于configure的情况下返回写确认[`slaveDelay`](https://docs.mongodb.com/manual/reference/replica-configuration/#rsconf.members\[n].slaveDelay)。有关实例何时确认写入的信息，请参见[确认行为](https://docs.mongodb.com/manual/reference/write-concern/#wc-ack-behavior)[`mongod`](https://docs.mongodb.com/manual/reference/program/mongod/#bin.mongod)。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `"majority"`                  | 请求确认写入操作已传播到所[计算的大多数](https://docs.mongodb.com/manual/reference/write-concern/#calculating-majority-count)含数据投票成员（即具有的[`members[n\].votes`](https://docs.mongodb.com/manual/reference/replica-configuration/#rsconf.members\[n].votes)大于的主要和次要成员 `0`）。例如，考虑一个具有3个投票成员的复制集，即Primary-Secondary-Secondary（PSS）。对于此复制集， [计算出的多数](https://docs.mongodb.com/manual/reference/write-concern/#calculating-majority-count)为2，并且写入必须传播到主要对象和一个辅助对象，以向客户端确认写入问题。注意[隐藏](https://docs.mongodb.com/manual/core/replica-set-hidden-member/#replica-set-hidden-members)， [延迟](https://docs.mongodb.com/manual/core/replica-set-delayed-member/#replica-set-delayed-members)和[优先级为0的](https://docs.mongodb.com/manual/core/replica-set-priority-0-member/#replica-set-secondary-only-members) 成员（[`members[n\].votes`](https://docs.mongodb.com/manual/reference/replica-configuration/#rsconf.members\[n].votes)大于`0` 可以确认\[`"majority"`]\([https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority")写入操作）。延迟的辅助副本可以在不早于configure的情况下返回写确认\[\`slaveDelay\`\](https://docs.mongodb.com/manual/reference/replica-configuration/#rsconf.members\[n\].slaveDelay)。在写操作返回确认给客户端之后，客户端可以使用readConcern](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority"%29写入操作）。延迟的辅助副本可以在不早于configure的情况下返回写确认\[`slaveDelay`]%28https://docs.mongodb.com/manual/reference/replica-configuration/#rsconf.members\[n].slaveDelay%29。在写操作返回确认给客户端之后，客户端可以使用readConcern) 读取该写操作的结果 。\[`w: "majority"`]\([https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority")\[\`"majority"\`\](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")有关实例何时确认写入的信息，请参见\[确认行为\](https://docs.mongodb.com/manual/reference/write-concern/#wc-ack-behavior)\[\`mongod\`\](https://docs.mongodb.com/manual/reference/program/mongod/#bin.mongod)。](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority"%29\[`"majority"`]%28https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29有关实例何时确认写入的信息，请参见\[确认行为]%28https://docs.mongodb.com/manual/reference/write-concern/#wc-ack-behavior%29\[`mongod`]%28https://docs.mongodb.com/manual/reference/program/mongod/#bin.mongod%29。) |
| `<custom write concern name>` | 请求确认写操作已传播到[`tagged`](https://docs.mongodb.com/manual/reference/replica-configuration/#rsconf.members\[n].tags)满足中定义的自定义写关注点的成员 [`settings.getLastErrorModes`](https://docs.mongodb.com/manual/reference/replica-configuration/#rsconf.settings.getLastErrorModes)。有关示例，请参阅“ [自定义多数据中心写入问题”](https://docs.mongodb.com/manual/tutorial/configure-replica-set-tag-sets/#configure-custom-write-concern)。如果自定义写入问题仅需要在写入操作复制到任何辅助数据库之前先要求主要数据库和主要数据库降级的确认，则可以[回滚](https://docs.mongodb.com/manual/core/replica-set-rollbacks/#rollback-avoid)数据。有关 实例何时确认写入的信息，请参见[确认行为](https://docs.mongodb.com/manual/reference/write-concern/#wc-ack-behavior)[`mongod`](https://docs.mongodb.com/manual/reference/program/mongod/#bin.mongod)。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |

**也可以看看**

* [默认的MongoDB读问题/写问题](https://docs.mongodb.com/manual/reference/mongodb-defaults/)
* [复制集协议版本](https://docs.mongodb.com/manual/reference/replica-set-protocol-versions/)

### j 选项

该`j`选项要求MongoDB确认写入操作已写入[磁盘日志中](https://docs.mongodb.com/manual/core/journaling/)。

|     |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| --- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `j` | 如果为，则请求确认[w：中](https://docs.mongodb.com/manual/reference/write-concern/#wc-w)指定的 实例已写入磁盘日志中。本身并不能保证不会因副本集主故障转移而回滚写操作。`j: true`[`mongod`](https://docs.mongodb.com/manual/reference/program/mongod/#bin.mongod)`j: true` \_在版本3.2中进行了更改：\_使用时，MongoDB仅在请求数量的成员（包括主要成员）写入日志后才返回。不管[w：](https://docs.mongodb.com/manual/reference/write-concern/#wc-w)写入关注点如何，副本集中以前的写入关注点只要求[主](https://docs.mongodb.com/manual/reference/glossary/#term-primary)记录写到日志。[`j: true`](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern.j)[`j: true`](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern.j) |
|     |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |

> **\[success] Note**
>
> * 指定一个写入关注点，该关注点包含到正在运行且没有日志记录的 实例中会产生错误。`j: true`[`mongod`](https://docs.mongodb.com/manual/reference/program/mongod/#bin.mongod)
> * 如果启用日记功能，则可能暗示。的 副本集配置设置确定的行为。有关详细信息，请参见 [确认行为](https://docs.mongodb.com/manual/reference/write-concern/#wc-ack-behavior)。\[`w: "majority"`]\([https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority")\`j](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority"%29`j): true`[`writeConcernMajorityJournalDefault\`]\(<https://docs.mongodb.com/manual/reference/replica-configuration/#rsconf.writeConcernMajorityJournalDefault>).
> * 如果日志是启用的，\[`w: "majority"`]\(<https://docs.mongodb.com/master/reference/write-concern/#writeconcern."majority>") 可能意味着**j：true**。[`writeConcernMajorityJournalDefault`](https://docs.mongodb.com/master/reference/replica-configuration/#rsconf.writeConcernMajorityJournalDefault) 复制集配置设置决定了行为。有关详细信息，请参阅[确认行为](https://docs.mongodb.com/master/reference/write-concern/#wc-ack-behavior) 。

### wtimeout

此选项指定写入问题的 time 限制(以毫秒为单位)。 `wtimeout`仅适用于大于`1`的`w`值。

`wtimeout`导致写入操作返回到指定限制后的错误，即使所需的写入关注最终会成功。当这些写操作 return 时，MongoDB 不会撤消在写入关注超过`wtimeout` time 限制之前执行的成功数据修改。

如果未指定`wtimeout`选项且写入关注的 level 无法实现，则写入操作将无限期阻止。指定`0`的`wtimeout` value 等同于没有`wtimeout`选项的写入问题。

## 确认行为

当[`mongod`](https://docs.mongodb.com/master/reference/program/mongod/#bin.mongod)实例确认写操作时 [w](https://docs.mongodb.com/master/reference/write-concern/#wc-w)选项和 [j](https://docs.mongodb.com/master/reference/write-concern/#wc-j) 选项决定。

### 独立

独立[`mongod`](https://docs.mongodb.com/manual/reference/program/mongod/#bin.mongod)应用程序在应用了内存中的写入之后或写入磁盘日志后会确认写入操作。下表列出了独立服务器的确认行为以及相关的写入问题：

|                 |                   |          |           |
| --------------- | ----------------- | -------- | --------- |
|                 | `j` 未指定           | `j:true` | `j:false` |
| `w: 1`          | 在记忆中              | 磁盘日志     | 在内存中      |
| `w: "majority"` | 磁盘日志（*如果与日志一起运行）* | 磁盘日志     | 在内存中      |

> **\[success] Note**
>
> 随着[`writeConcernMajorityJournalDefault`](https://docs.mongodb.com/manual/reference/replica-configuration/#rsconf.writeConcernMajorityJournalDefault)设置为`false`，MongoDB的不等待 写入承认写之前被写入到磁盘上的日志。这样，在给定副本集中的大多数节点出现瞬时丢失（例如崩溃和重新启动）的情况下，写操作可能会回滚。\[`w: "majority"`]\([https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority")\`majority\`](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority"%29`majority`)

### 复制集

指定给[w](https://docs.mongodb.com/manual/reference/write-concern/#wc-w)的值确定返回成功之前必须确认写入的复制集成员的数量。对于每个合格的复制集成员，[j](https://docs.mongodb.com/manual/reference/write-concern/#wc-j) 选项确定成员是在内存中应用写操作之后还是在写到磁盘日志上之后是否确认写。

**w: "majority"**

复制集的任何带有数据的投票成员都可以对\[`"majority"`]\([https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority")写操作进行写确认。](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority"%29写操作进行写确认。)

下表列出了成员何时可以基于[j](https://docs.mongodb.com/manual/reference/write-concern/#wc-j)值确认写入：

|            |                                                                                                                                                                                                                                                                                                                                                                                            |
| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `j`是不确定的   | 确认取决于[`writeConcernMajorityJournalDefault`](https://docs.mongodb.com/master/reference/replica-configuration/#rsconf.writeConcernMajorityJournalDefault)的值: 如果为true，确认需要对磁盘上的日志进行写入操作(j: true) [`writeConcernMajorityJournalDefault`](https://docs.mongodb.com/master/reference/replica-configuration/#rsconf.writeConcernMajorityJournalDefault)默认为true 如果为false，确认需要在内存中进行写入操作(j: false)。 |
| `j: true`  | 确认需要对磁盘日志进行写入操作。                                                                                                                                                                                                                                                                                                                                                                           |
| `j: false` | 确认需要在内存中进行写入操作。                                                                                                                                                                                                                                                                                                                                                                            |

> **\[success] Note**
>
> 行为细节,参见 [w: "majority" Behavior](https://docs.mongodb.com/master/reference/write-concern/#wc-majority-behavior).

**w: <`number`>**

复制集的任何承载数据的成员都可以参与[`w：<number>`](https://docs.mongodb.com/manual/reference/write-concern/#wc-w)写操作的写确认。

下表列出了成员何时可以基于[j](https://docs.mongodb.com/manual/reference/write-concern/#wc-j)值确认写入：

|            |                          |
| ---------- | ------------------------ |
| `j` 未指定    | 确认需要在内存中进行写操作(j: false)。 |
| `j: true`  | 确认需要将操作写入磁盘日志。           |
| `j: false` | 确认需要在内存中进行写操作。           |

> 注意
>
> [隐藏](https://docs.mongodb.com/manual/core/replica-set-hidden-member/#replica-set-hidden-members)， [延迟](https://docs.mongodb.com/manual/core/replica-set-delayed-member/#replica-set-delayed-members)和[优先级为0](https://docs.mongodb.com/manual/core/replica-set-priority-0-member/#replica-set-secondary-only-members) 的成员可以确认[`w:<number>`](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern.)写操作。
>
> 延迟的辅助程序可以不早于配置的slaveDelay返回写确认。

## 因果一致的会话和写问题

使用[因果一致的客户机会话](https://docs.mongodb.com/manual/core/read-isolation-consistency-recency/#sessions)，客户机会话仅在以下情况下保证因果一致性：

* 相关的读取操作使用\[`"majority"`]\([https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")读取关注，并且](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29读取关注，并且)
* 相关的写操作使用\[`"majority"`]\(<https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority>") 写关注。

有关详细信息，请参见[因果一致性](https://docs.mongodb.com/manual/core/read-isolation-consistency-recency/#causal-consistency)。

### `w: "majority"` 的行为

* [`writeConcernMajorityJournalDefault`](https://docs.mongodb.com/master/reference/replica-configuration/#rsconf.writeConcernMajorityJournalDefault)设置为**false**，MongoDB不等待\[`w: "majority"`]\(<https://docs.mongodb.com/master/reference/write-concern/#writeconcern."majority>") 写入被写入到磁盘日志之前，确认写入，因此，在给定复制集中的大多数节点出现短暂损失(例如崩溃和重新启动)时，大多数写操作可能会回滚。
* [隐藏的](https://docs.mongodb.com/master/core/replica-set-hidden-member/#replica-set-hidden-members), [延迟的](https://docs.mongodb.com/master/core/replica-set-delayed-member/#replica-set-delayed-members), and [priority 0](https://docs.mongodb.com/master/core/replica-set-priority-0-member/#replica-set-secondary-only-members)的成员，成员数为\[n]。投票大于0可以确认\[`"majority"`]\(<https://docs.mongodb.com/master/reference/write-concern/#writeconcern."majority>") ”写操作。

## 计算关注的多数

> 提示
>
> 从版本4.2.1开始，[`rs.status()`](https://docs.mongodb.com/manual/reference/method/rs.status/#rs.status)返回[`writeMajorityCount`](https://docs.mongodb.com/manual/reference/command/replSetGetStatus/#replSetGetStatus.writeMajorityCount)包含计算出的多数数的 字段。

写入关注的多数\[`"majority"`]\([https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority")由以下值中的较小者计算得出：](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority"%29由以下值中的较小者计算得出：)

* 所有投票成员（包括仲裁员）中的大多数
* 所有**带有数据的**投票成员的数量。

> **\[warning] 警告**
>
> 如果计算出的多数数等于所有**带有数据的**投票成员的人数（例如，由3个成员组成的主要-次要仲裁员部署），则写关注 \[`"majority"`]\([https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority")可能会超时，或者如果有数据的投票成员则永远不会得到承认掉线或无法到达。如果可能，请使用带有数据的投票成员而不是仲裁者。](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority"%29可能会超时，或者如果有数据的投票成员则永远不会得到承认掉线或无法到达。如果可能，请使用带有数据的投票成员而不是仲裁者。)

例如，考虑：

* 具有3个投票成员的复制集，主要-次要（PSS）：
  * 所有投票成员中大多数为2。
  * 所有有数据投票的成员人数为3。

计算得出的多数为2，最小值为2和3。写入必须传播到主要对象和辅助对象之一，\[`"majority"`]\([https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority")以向客户端确认写入问题。](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority"%29以向客户端确认写入问题。)

* 复制集包含3个投票成员，主要-次要仲裁员（PSA）
  * 所有投票成员中大多数为2。
  * 所有有数据投票的成员人数为2。

计算得出的多数为2，为2和2的最小值。由于该写操作只能应用于数据承载成员，因此该写操作必须传播到主要对象和辅助对象，\[`"majority"`]\([https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority")以向客户端确认写问题。](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority"%29以向客户端确认写问题。)

> 提示
>
> 避免在a (p - a)或其他拓扑结构中使用“多数”写关注点，这些拓扑结构要求所有支持数据的投票成员都可用来确认写操作。想要使用\*\*“majority”\*\*写关注点的持久性保证的客户应该部署不需要所有数据承载投票成员可用的拓扑(例如P-S-S)。

### 写问题出处

从4.4版本开始，MongoDB跟踪写关注点的来源，它表示一个特定的写关注点的来源。您可能会在[`getLastError`](https://docs.mongodb.com/master/reference/command/serverStatus/#serverstatus.metrics.getLastError) 指标、write concern error对象和MongoDB日志中看到显示出处的信息。

下表显示了可能的写问题**provenance**值及其重要性:

| Provenance             | Description                                                                                                                                    |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `clientSupplied`       | 写关注点是在应用程序中指定的。                                                                                                                                |
| `customDefault`        | 写关注点源自自定义的默认值。参见[`setDefaultRWConcern`](https://docs.mongodb.com/master/reference/command/setDefaultRWConcern/#dbcmd.setDefaultRWConcern).     |
| `getLastErrorDefaults` | 写关系起源于复制集的设置[`getLastErrorDefaults`](https://docs.mongodb.com/master/reference/replica-configuration/#rsconf.settings.getLastErrorDefaults)字段。 |
| `implicitDefault`      | 在没有其他所有写关注规范的情况下，写关注源自服务器。                                                                                                                     |

译者：杨帅 张琦

校对：杨帅


# MongoDB CRUD概念

本节包含与MongoDB中的CRUD操作相关的其他概念的信息。

**原子性，一致性和分布式操作**

* [原子性和事务](https://docs.mongodb.com/manual/core/write-operations-atomicity/)
* [阅读隔离度，一致性和近效性](https://docs.mongodb.com/manual/core/read-isolation-consistency-recency/)
* [分布式查询](https://docs.mongodb.com/manual/core/distributed-queries/)
* [通过findAndModify进行线性化读取](https://docs.mongodb.com/manual/tutorial/perform-findAndModify-linearizable-reads/)

**查询计划，性能和分析**

* [查询计划](https://docs.mongodb.com/manual/core/query-plans/)
* [查询优化](https://docs.mongodb.com/manual/core/query-optimization/)
* [分析查询性能](https://docs.mongodb.com/manual/tutorial/analyze-query-plan/)
* [写操作性能](https://docs.mongodb.com/manual/core/write-performance/)

**其它**

* [Tailable 游标](https://docs.mongodb.com/manual/core/tailable-cursors/)

也可以看看：

[事务](https://docs.mongodb.com/manual/core/transactions/)

译者：杨帅

校对：杨帅


# 原子性和事务


# 读隔离性，一致性和近因性

**在本页面**

* [隔离保证](#隔离)
* [单调写](#单调)
* [实时顺序](#订单)
* [因果一致性](#因果)

## 隔离保证

### 读取未提交

根据读取的关注点，客户端可以在[持久](https://docs.mongodb.com/manual/reference/glossary/#term-durable)写入之前看到写入的结果：

* 不考虑一个写操作的[写关注](https://docs.mongodb.com/manual/reference/write-concern/)，其他客户端使用`local`或者`available`的读关注级别都可以看到写操作的结果。
* 使用`local`或`available`读取关注级别的客户端可以读取数据，这些数据随后可能会在副本集故障转移期间回滚。

对于[多文档事务](https://docs.mongodb.com/manual/core/transactions/)中的操作，当事务提交时，在事务中进行的所有数据更改都将保存并在事务外部可见。也就是说，一个事务在回滚其他事务时将不会提交其某些更改。

在提交事务之前，在事务外部看不到在事务中进行的数据更改。

但是，当事务写入多个分片时，并非所有外部读取操作都需要等待已提交事务的结果在所有分片上可见。例如，如果提交了一个事务，并且在分片A上可以看到写1，但是在分片B上还看不到写2，则外部一个读关注级别为`local`的读操作可以读取写1的结果而看不到写2。

读未提交是默认的隔离级别，适用于mongod独立实例以及复制集和分片群集。

### 读取未提交和单个文档原子性

对于单个文档，写操作是原子性的。 即，如果写操作正在更新文档中的多个字段，则读操作将永远不会看到仅更新了某些字段的文档。 但是，尽管客户端可能看不到部分更新的文档，但读未提交意味着并发读取操作仍可以在使更改持久之前看到更新的文档。

对于以独立模式部署的 [`mongod`](https://docs.mongodb.com/manual/reference/program/mongod/#bin.mongod) 实例，对单个文档的一组读写操作是线性的。 使用复制集时，只有在没有回滚的情况下，对单个文档的一组读取和写入操作才是线性的。

### 读取未提交和多文档写入

当单个写入操作（例如 [`db.collection.updateMany()`](https://docs.mongodb.com/manual/reference/method/db.collection.updateMany/#db.collection.updateMany)）修改多个文档时，每个文档的修改都是原子的，但整个操作不是原子的。

当单个写入操作（例如`db.collection.updateMany()`）修改多个文档时，每个文档的修改都是原子的，但整个操作不是原子的。

当执行多文档写操作时，无论是通过单个写操作还是通过多个写操作，其他操作都可能会交错。

对于需要原子性地读写多个文档（在单个或多个集合中）的情况，MongoDB支持多文档事务：

* 4.0版本中，MongoDB支持副本集内的多文档事务。
* 4.2版本中，MongoDB引入了分布式事务，从而增加了对分片群集上多文档事务的支持，并结合了对副本集上多文档事务的现有支持。

关于MongoDB事务的细节，请参考[事务](https://docs.mongodb.com/manual/core/transactions/)页。

> **\[warning] 重要**
>
> 在大多数情况下，与单文档写入相比，多文档事务产生的性能成本更高，并且多文档事务的可用性并不能替代有效的架构设计。 在许多情况下，[非结构化化数据模型(嵌入式文档和数组)](https://docs.mongodb.com/manual/core/data-model-design/#data-modeling-embedding)将继续是您的数据和用例的最佳选择。 也就是说，在许多情况下，适当地对数据建模将最大程度地减少对多文档交易的需求。
>
> 关于其他事务使用方面的注意事项(比如运行时显示和oplog大小限制等)，请参考[生产注意事项](https://docs.mongodb.com/manual/core/transactions-production-consideration/).

在不隔离多文档写入操作的情况下，MongoDB表现出以下行为：

1. **非时间点(`Non-point-in-time`)读取操作**。假设读取操作在时间t1开始并开始读取文档。然后，写操作在稍后的某个时间t2提交对其中一个文档的更新。读操作可能会看到文档的更新后版本，因此看不到数据的point-in-time快照。
2. **非可序列化的操作**。假设读取操作在时间t1读取文档d1，而写入操作在稍后的时间t3更新d1。这引入了读写依赖性，因此，如果要序列化操作，则读取操作必须先于写入操作。但是还假设写操作在时间t2更新文档d2，而读取操作随后在稍后的时间t4读取d2。这就引入了写-读依赖关系，它将要求读操作在可序列化时间表中在写操作之后进行。有一个依赖循环，使可序列化成为不可能。
3. 读取操作可能会丢失在读取操作过程中更新的匹配文档。

### 游标快照

在某些情况下，MongoDB游标可以多次返回同一个文档。 当游标返回文档时，其他操作可能会与查询交错。 如果其中某些操作更改了查询使用的索引上的索引字段； 那么光标将多次返回同一文档。

如果您的集合中有一个或多个从未修改过的字段，则可以在此字段或这些字段上使用唯一索引，这样查询将最多返回每个文档一次。 使用`hint()`查询可显式强制查询使用该唯一索引。

## 单调写

**默认的，对于standalone和复制集，MongoDB提供单调写入保证。**

对于分片集群的单调写入，参考[因果一致性](https://docs.mongodb.com/manual/core/read-isolation-consistency-recency/#causal-consistency)。

## 实时顺序

*3.4后新引入*

对于主节点上的读取和写入操作，如果将读关注设置为`linearizable`，将写关注设置为`majority`，那么这种读写模型组合可以使多个线程可以在单个文档上执行读写操作，就好像单个线程实时执行了这些操作一样 ; 也就是说，这些读写的相应计划被认为是线性的。

亦可参考：

[因果一致性](https://docs.mongodb.com/manual/core/read-isolation-consistency-recency/#causal-consistency)

## 因果一致性

*3.6后新引入*

如果操作在逻辑上取决于先前的操作，则这些操作之间存在因果关系。 例如，基于指定条件删除所有文档的写入操作和验证删除操作的后续读取操作具有因果关系。

在因果一致的会话中，MongoDB按照尊重因果关系的顺序执行因果操作，并且客户观察到与因果关系一致的结果。

### 客户端会话与因果一致性保证

为了提供因果一致性，MongoDB 3.6在客户端会话中启用因果一致性。 因果一致的会话表示具有`majority`的读关注级别的读操作和具有`majority`的写关注级别的写操作的关联序列具有因果关系，这由它们的顺序反映出来。 **应用程序必须确保一次只有一个线程在客户端会话中执行这些操作**。

对于因果相关的操作：

1. 客户端开始一个客户端会话

   > **\[warning] 重要**
   >
   > 客户端会话仅在以下情况下保证因果一致性：
   >
   > * 读取操作的读关注级别为`majority`；即返回数据已被大多数副本集成员确认并且是持久化的。
   > * 写操作的写关注级别为`majority`；即要求确认该操作已应用于副本集中大多数可投票成员。
   >
   >   关于因果一致性和多种读关注级别/写关注级别，请参考[因果一致性和读/写关注级别](https://docs.mongodb.com/manual/core/causal-consistency-read-write-concerns/)。
2. 当客户端发出具有`majority`读关注和`majority`写关注的读取序列时，客户端将会话信息包含在每个操作中。
3. 对于与会话相关联的每个具有`majority`读关注的读取操作和具有`majority`写关注的写入操作，即使操作出错，MongoDB也会返回操作时间和集群时间。 客户端会话跟踪操作时间和群集时间。

   > **\[success] 注意**
   >
   > 对于未确认的`（w：0）`写操作，MongoDB不返回操作时间和群集时间。未经确认的写入并不表示任何因果关系。
   >
   > 尽管MongoDB在客户端会话中返回读操作和已确认写操作的操作时间和集群时间，但是只有具有`majority`读关注的读取操作和具有`majority`写关注的写入操作才能保证因果一致性。 有关详细信息，请参见[因果一致性和读/写关注级别](https://docs.mongodb.com/manual/core/causal-consistency-read-write-concerns/)。
4. 相关的客户端会话会跟踪这两个时间字段。

   > **\[success] 注意**
   >
   > 不同会话之间的操作可以因果一致。 MongoDB驱动程序和mongo Shell提供了推进客户端会话的操作时间和集群时间的方法。 因此，客户端可以推进一个客户端会话的群集时间和操作时间，使其与另一客户端会话的操作保持一致。

#### 因果一致性保证

下表列出了因果一致会话为具有`majority`读关注的读取操作和具有`majority`写关注点的写入操作提供的因果一致性保证。

| 保证  | 描述                                                                                               |
| --- | ------------------------------------------------------------------------------------------------ |
| 写后读 | 读操作可以正确读到之前写的结果。                                                                                 |
| 单调读 | 多个读操作会返回一样的 比如在一个会话中“ - 写操作1在写操作2前， - 读操作1在读操作2前，并且， - 读操作1返回了写操作2的结果 那么读操作2并不会返回写操作1的结果。        |
| 单调写 | 写操作按顺序进行。 比如，如果会话中写操作1在写操作2前，数据在写操作2的状态必须是写操作1完成后的状态。其他写入操作可以在写操作1和写操作2之间进行交错，但写操作2不可能在写操作1之前进行。 |
| 读后写 | 写操作在读操作后执行。 即，写入时的数据状态必须包含之前的读取操作的数据状态。                                                          |

#### 读偏好

这些保证适用于MongoDB部署的所有成员。 例如，如果在因果关系一致的会话中发出具有`majority`写关注级别的写操作，然后发出一个具有`majority`读关注级别的从节点（即，读偏好为`secondary`）读操作，则读取操作将反映写入操作后的数据库状态。

#### 隔离性

**因果一致的会话内的操作与会话外的操作不是隔离的**。 如果并发写操作在会话的写操作和读取操作之间交错，则会话的读操作可能返回反映会话写操作之后发生的写操作的结果。

### MongoDB驱动

> 提示：
>
> 应用程序必须确保一次只有一个线程在客户端会话中执行这些操作。

客户端需要使用MongoDB 3.6或更高版本的MongoDB驱动程序：

| Java 3.6+   | C# 2.5+   | Perl 2.0+  |
| ----------- | --------- | ---------- |
| Python 3.6+ | Node 3.0+ | PHPC 1.4+  |
| C 1.9+      | Ruby 2.5+ | Scala 2.2+ |

### 示例

> 重要\*\*
>
> 因果一致性会话只能保证对于读关注级别为`majority`以及写关注级别为`majority`的读取操作的因果一致性。

考虑一个维护各种项目的当前和历史数据的`items`集合。 只有历史数据的`end`日期为非空。 如果项目的`sku`值更改，则具有旧`sku`值的文档需要使用`end`日期进行更新，此后，将使用当前`sku`值插入新文档。 客户端可以使用因果一致的会话来确保更新在插入之前发生。

(以python为例，其他实例查看原链接)

```
with client.start_session(causal_consistency=True) as s1:
    current_date = datetime.datetime.today()
    items = client.get_database(
        'test', read_concern=ReadConcern('majority'),
        write_concern=WriteConcern('majority', wtimeout=1000)).items
    items.update_one(
        {'sku': "111", 'end': None},
        {'$set': {'end': current_date}}, session=s1)
    items.insert_one(
        {'sku': "nuts-111", 'name': "Pecans",
         'start': current_date}, session=s1)
```

如果另一个客户端需要读取所有当前的sku值，则可以将集群时间和操作时间推进到另一个会话的集群时间和操作时间，以确保该客户端与另一个会话有因果关系，并在两次写入之后读取：

```
with client.start_session(causal_consistency=True) as s2:
    s2.advance_cluster_time(s1.cluster_time)
    s2.advance_operation_time(s1.operation_time)

    items = client.get_database(
        'test', read_preference=ReadPreference.SECONDARY,
        read_concern=ReadConcern('majority'),
        write_concern=WriteConcern('majority', wtimeout=1000)).items
    for item in items.find({'end': None}, session=s2):
        print(item)
```

### 限制

以下生成内存数据结构的操作并不是因果一致性的：

| 操作                                                                                                                                      | 备注                           |
| --------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- |
| [`collStats`](https://docs.mongodb.com/manual/reference/command/collStats/#dbcmd.collStats)                                             |                              |
| [`$collStats`](https://docs.mongodb.com/manual/reference/operator/aggregation/collStats/#pipe._S_collStats) with `latencyStats` option. |                              |
| [`$currentOp`](https://docs.mongodb.com/manual/reference/operator/aggregation/currentOp/#pipe._S_currentOp)                             | 如果操作和一个因果一致性的客户端会话相关，则会返回错误。 |
| [`createIndexes`](https://docs.mongodb.com/manual/reference/command/createIndexes/#dbcmd.createIndexes)                                 |                              |
| [`dbHash`](https://docs.mongodb.com/manual/reference/command/dbHash/#dbcmd.dbHash)                                                      | MongoDB4.2以后的版本才支持           |
| [`dbStats`](https://docs.mongodb.com/manual/reference/command/dbStats/#dbcmd.dbStats)                                                   |                              |
| [`getMore`](https://docs.mongodb.com/manual/reference/command/getMore/#dbcmd.getMore)                                                   | 如果操作和一个因果一致性的客户端会话相关，则会返回错误。 |
| [`$indexStats`](https://docs.mongodb.com/manual/reference/operator/aggregation/indexStats/#pipe._S_indexStats)                          |                              |
| [`mapReduce`](https://docs.mongodb.com/manual/reference/command/mapReduce/#dbcmd.mapReduce)                                             | MongoDB4.2以后的版本才支持           |
| [`ping`](https://docs.mongodb.com/manual/reference/command/ping/#dbcmd.ping)                                                            | 如果操作和一个因果一致性的客户端会话相关，则会返回错误。 |
| [`serverStatus`](https://docs.mongodb.com/manual/reference/command/serverStatus/#dbcmd.serverStatus)                                    | 如果操作和一个因果一致性的客户端会话相关，则会返回错误。 |
| [`validate`](https://docs.mongodb.com/manual/reference/command/validate/#dbcmd.validate)                                                | MongoDB4.2以后的版本才支持           |

原文链接：<https://docs.mongodb.com/manual/core/read-isolation-consistency-recency/#>

译者：刘翔 杨帅

校对：徐雷


# 因果一致性和读写关注

通过MongoDB的[因果一致性客户端会话](https://docs.mongodb.com/manual/core/read-isolation-consistency-recency/#sessions)，读写问题的不同组合可提供不同的 [因果一致性保证](https://docs.mongodb.com/manual/core/read-isolation-consistency-recency/#causal-consistency-guarantees)。如果定义因果一致性以表示耐久性，则下表列出了各种组合提供的特定保证：

| 阅读关注                                                                                                        | 写关注                                                                                                  | 阅读自己的文章 | 单调读 | 单调写 | 写跟读 |
| ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | ------- | --- | --- | --- |
| \[`"majority"`]\(<https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority>") | \[`"majority"`]\(<https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority>") | ✅       | ✅   | ✅   | ✅   |
| \[`"majority"`]\(<https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority>") | [`{ w: 1 }`](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern.)                 |         | ✅   |     | ✅   |
| \[`"local"`]\(<https://docs.mongodb.com/manual/reference/read-concern-local/#readconcern."local>")          | [`{ w: 1 }`](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern.)                 |         |     |     |     |
| \[`"local"`]\(<https://docs.mongodb.com/manual/reference/read-concern-local/#readconcern."local>")          | \[`"majority"`]\(<https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority>") |         |     | ✅   |     |

如果因果一致性表示持久性，那么从表中可以看出，只有具有\[`"majority"`]\([https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")读关注度的读取操作和具有\[\`"majority"\`\](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority")写关注度的写入操作才能保证所有四个因果一致性保证。也就是说，](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29读关注度的读取操作和具有\[`"majority"`]%28https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority"%29写关注度的写入操作才能保证所有四个因果一致性保证。也就是说，) [因果一致的客户端会话](https://docs.mongodb.com/manual/core/read-isolation-consistency-recency/#sessions)只能保证以下方面的因果一致性：

* \[`"majority"`]\([https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")关注阅读操作；也就是说，读取操作将返回大多数复制集成员已确认且持久的数据。](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29关注阅读操作；也就是说，读取操作将返回大多数复制集成员已确认且持久的数据。)
* \[`"majority"`]\([https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority")关注写操作；也就是说，写操作要求确认该操作已应用于大多数复制集的有投票权的成员。](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority"%29关注写操作；也就是说，写操作要求确认该操作已应用于大多数复制集的有投票权的成员。)

如果因果一致性并不意味着持久性(即，写操作可能会回滚)，则具有写顾虑的写操作也可以提供因果一致性。[`{ w: 1 }`](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern.)

> **\[success] 注意**
>
> 在某些情况下(但不一定在所有情况下)，读和写关注点的其他组合也可以满足所有四个因果一致性保证。

读关注点\[`"majority"`]\([https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")和写关注点](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29和写关注点) \[`"majority"`]\([https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority")确保即使在复制集中的两个成员\*短暂地\*认为它们是主要的\[情况下(例如，使用网络分区)\](https://docs.mongodb.com/manual/core/read-preference-use-cases/#edge-cases)，这四个因果一致性保证也成立](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority"%29确保即使在复制集中的两个成员*短暂地*认为它们是主要的\[情况下%28例如，使用网络分区%29]%28https://docs.mongodb.com/manual/core/read-preference-use-cases/#edge-cases%29，这四个因果一致性保证也成立) 。尽管两个主数据库都可以完成写操作，但是只有一个主数据库能够完成写操作。[`{ w: 1 }`](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern.)\[`"majority"`]\(<https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority>").

例如，考虑网络分区划分五个成员复制集的情况：

![网络分区：一侧选择了新的主节点，而旧的主节点尚未卸任。](https://docs.mongodb.com/manual/_images/network-partition-two-primaries.svg)

## 场景

为了说明读写关注点要求，在以下情况下，客户端向客户端发出了一系列操作，并对复制集进行了读写关注点的各种组合：

* [阅读关注“多数”并写关注“多数”](https://docs.mongodb.com/manual/core/causal-consistency-read-write-concerns/#causal-rc-majority-wc-majority)
* [阅读关注“多数”并发表关注{w：1}](https://docs.mongodb.com/manual/core/causal-consistency-read-write-concerns/#causal-rc-majority-wc-1)
* [阅读关注“本地”，写关注“多数”](https://docs.mongodb.com/manual/core/causal-consistency-read-write-concerns/#causal-rc-local-wc-majority)
* [阅读关注“本地”并写关注{w：1}](https://docs.mongodb.com/manual/core/causal-consistency-read-write-concerns/#causal-rc-local-wc-1)

### 阅读关注`"majority"`和写关注`"majority"`

在因果一致的会话中使用读取关注\[`"majority"`]\([https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")和写入关注](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29和写入关注) \[`"majority"`]\([https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority")可提供以下因果一致性保证：](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority"%29可提供以下因果一致性保证：)

✅自己读✅单调读read单调写✅写跟随读

**方案1（读关注"majority"和写关注"majority"）**

在具有两个主操作的过渡期内，由于只有**P**new操作才能满足写关注的写操作，因此客户机会话可以成功发出以下操作序列：\[`{ w: "majority" }`]\(<https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority>")

| 序列                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 | 例                                                                              |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| 1.write1\[`"majority"`]\(<https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority>") 到 新的关注**P**new 2.read1>与读关心\[`"majority"`]\([https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")到\*\*S\*\*](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29到**S**)2 3.write2\[`"majority"`]\([https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority")到新的关注\*\*P\*\*](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority"%29到新的关注**P**)new 4.read2与读取关注\[`"majority"`]\([https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")到\*\*S\*\*](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29到**S**)3 | 对于项目`A`，更新`qty`为`50`。 阅读项目`A`。对于`qty`小于或等于的项目`50`， 更新`restock`到`true`。阅读项目`A`。 |

![使用读关注多数和写关注多数的具有两个原语的数据状态](https://docs.mongodb.com/manual/_images/causal-rc-majority-wc-majority.svg)

|            |                                                                                 |
| ---------- | ------------------------------------------------------------------------------- |
| ✅ **自己写**  | read1从**S**2读取数据，该数据反映了write1之后的状态。read2从**S**1读取数据，该数据反映了write1之后是write2之后的状态。 |
| ✅ **单调读**  | read2从**S**3中读取反映read1之后状态的数据。                                                  |
| ✅ **单调写**  | write2更新**P**new数据，以反映write1之后的状态。                                              |
| ✅ **写跟随读** | write2更新**P**new数据，以反映read1之后的数据状态（即，较早的状态反映read1读取的数据）。                        |

**方案2（读取关注“多数”和写入关注“多数”）**

考虑一个替代序列，其中具有读关注的read1\[`"majority"`]\([https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")路由到\`S\`1：](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29路由到`S`1：)

| 序列                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 | 例                                                                              |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| 1.write1\[`"majority"`]\(<https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority>") 到 新的关注**P**new 2.read1>与读关心\[`"majority"`]\([https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")到\*\*S\*\*](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29到**S**)2 3.write2\[`"majority"`]\([https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority")到新的关注\*\*P\*\*](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority"%29到新的关注**P**)new 4.read2与读取关注\[`"majority"`]\([https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")到\*\*S\*\*](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29到**S**)3 | 对于项目`A`，更新`qty`为`50`。 阅读项目`A`。对于`qty`小于或等于的项目`50`， 更新`restock`到`true`。阅读项目`A`。 |

在这个序列中，read1在**P**old上的多数提交点提前之前不能返回。在**P**old和**S**1能够与复制集的其余部分通信之前，这是不可能发生的;此时，**P**old已经退出(如果还没有)，两个成员从副本集中的其他成员同步(包括write1)。

|            |                                                                                                      |
| ---------- | ---------------------------------------------------------------------------------------------------- |
| ✅ **自己写**  | read1反映了write11之后的数据状态，尽管在网络分区已修复并且该成员已与副本集的其他成员进行同步之后。read2从**S**3读取数据，该数据反映了write11之后是write2之后的状态。 |
| ✅ **单调读**  | read2从**S**3读取数据，该数据反映read1之后的状态（即，较早的状态反映在read1读取的数据中）。                                             |
| ✅ **单调写**  | write2更新**P**new数据，以反映write1之后的状态。                                                                   |
| ✅ **写跟随读** | write2更新**P**new数据，以反映read1之后的数据状态（即，较早的状态反映read1读取的数据）。                                             |

#### 读关注`"majority"`和写关注`{w: 1}`

\_如果因果一致性暗示持久性，则\_在因果一致性会话中使用读关注\[`"majority"`]\([https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")和写关注](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29和写关注) 可提供以下因果一致性保证：[`{ w: 1 }`](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern.)

❌自己读 ✅单调读read单调写. ✅写跟随读

*如果因果一致性并不意味着持久性*：

✅自己读. ✅单调读read单调写. ✅写跟随读

**方案3（“关注多数”和“关注关注” ）{w: 1}**

在过渡期内有两个初选，因为无论**P**old与**P**new能满足与写入 的写入关注，一个客户端会话可以成功地发出以下的操作序列，但不是因果关系一致\*\*，如果一致因果意味着耐久性\*\*：[`{ w: 1 }`](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern.)

| 序列                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               | 例                                                                              |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ |
| 1.write1与写入关注 到 [`{ w: 1 }`](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern.)**P**old 2.read11与读关心\[`"majority"`]\([https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")到\*\*S\*\*](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29到**S**)2 3.write2到新的关注[`{ w: 1 }`](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern.)**P**new 4.read2与读取关注\[`"majority"`]\([https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")到\*\*S\*\*](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29到**S**)3 | 对于项目`A`，更新`qty`为`50`。 阅读项目`A`。对于`qty`小于或等于的项目`50`， 更新`restock`到`true`。阅读项目`A`。 |

![使用读关注多数和写关注1的具有两个原语的数据状态](https://docs.mongodb.com/manual/_images/causal-rc-majority-wc-1.svg)

按照这个顺序

* 直到**P**new上的大多数提交点超过了write1的时间，read1才会返回。
* 直到**P**new上的大多数提交点超过了write2的时间，read2才能返回。
* 当网络分区恢复时，write1将回滚。

➤ *如果因果一致性意味着持久性*

|            |                                                          |
| ---------- | -------------------------------------------------------- |
| ❌ **自己写**  | read1从**S**2读取的数据不反映write1之后的状态。                         |
| ✅ **单调读**  | read2从**S**3读取数据，该数据反映read1之后的状态（即，较早的状态反映在read1读取的数据中）。 |
| ❌ **单调写**  | write2更新了**P**new数据，而不会反映write1之后的状态。                    |
| ✅ **写跟随读** | write2更新**P**new数据，以反映read1之后的状态（即，较早的状态反映read1读取的数据）。   |

➤ *如果因果一致性并不意味着持久性*

|            |                                                          |
| ---------- | -------------------------------------------------------- |
| ✅ **自己写**  | read1从**S**2读取数据，返回反映与write1等效的状态的数据，然后回退write1。         |
| ✅ **单调读**  | read2从**S**3读取数据，该数据反映read1之后的状态（即，较早的状态反映在read1读取的数据中）。 |
| ✅ **单调写**  | write2更新了**P**new的数据，这等效于write1之后回退写1的数据。                |
| ✅ **写跟随读** | write2更新**P**new数据，以反映read1之后的状态（即，较早的状态反映read1读取的数据）。   |

**方案4（“关注多数”和“关注关注” ）{w: 1}**

考虑一个替代序列，其中具有读关注的读1\[`"majority"`]\([https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")路由到\`S\`1：](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29路由到`S`1：)

| 序列                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               | 例                                                                              |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ |
| 1.write1与写入关注 到 [`{ w: 1 }`](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern.)**P**old 2.read11与读关心\[`"majority"`]\([https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")到\*\*S\*\*](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29到**S**)1 3.write2到新的关注[`{ w: 1 }`](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern.)**P**new 4.read2与读取关注\[`"majority"`]\([https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")到\*\*S\*\*](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29到**S**)3 | 对于项目`A`，更新`qty`为`50`。 阅读项目`A`。对于`qty`小于或等于的项目`50`， 更新`restock`到`true`。阅读项目`A`。 |

按此顺序：

* 直到**S**1上的大多数提交点提高，read1才能返回。在**P**old和**S**1能够与复制集的其他成员进行通信之前，这是不可能发生的。此时，**P**old已经退出(如果还没有)，write1将从**P**old和**S**1回滚，两个成员将与复制集的其他成员同步。

➤ *如果因果一致性意味着持久性*

|            |                                                               |
| ---------- | ------------------------------------------------------------- |
| ❌ **自己写**  | read1读取的数据不反映已回退的write1的结果。                                   |
| ✅ **单调读**  | read2从**S**3读取数据，该数据反映read1之后的状态（即，其较早的状态反映read1读取的数据）。       |
| ❌ **单调写**  | write2更新关于**P**new的数据，该数据不反映write1之后的状态，该write1在write2之前但已回滚。 |
| ✅ **写跟随读** | write2更新**P**new数据，以反映read1之后的状态（即，其较早的状态反映read1读取的数据）。       |

➤ *如果因果一致性并不意味着持久性*

|            |                                                         |
| ---------- | ------------------------------------------------------- |
| ✅ **自己写**  | read1返回反映write1最终结果的数据，因为write1最终会回滚。                   |
| ✅ **单调读**  | read2从**S**3读取数据，该数据反映read1之后的状态（即，其较早的状态反映read1读取的数据）。 |
| ✅ **单调写**  | write2更新**P**new上的数据，这等效于write1之后回退write1的数据。           |
| ✅ **写跟随读** | write2更新**P**new数据，以反映read1之后的状态（即，其较早的状态反映read1读取的数据）。 |

#### 读关注`"local"`和写关注`{w: 1}`

在因果一致的会话中使用读关注\[`"local"`]\([https://docs.mongodb.com/manual/reference/read-concern-local/#readconcern."local")和写关注](https://docs.mongodb.com/manual/reference/read-concern-local/#readconcern."local"%29和写关注) 不能保证因果一致性。[`{ w: 1 }`](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern.)

❌自己读. ❌单调读read单调写. ❌写跟随读

在某些情况下（但不一定在所有情况下），此组合可以满足所有四个因果一致性保证。

**方案5（“本地关注”和“关注关注” ）{w: 1}**

在这个短暂的时期，因为无论**P**old与 **P**new能满足与写入的写入关注，一个客户端会话可以发出以下的操作序列成功，但不是因果关系是一致的：[`{ w: 1 }`](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern.)

| 序列                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              | 例                                                                              |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| 1.write1与写入关注到 [`{ w: 1 }`](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern.)**P**old 2.read11与读关心\[`"majority"`]\([https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")到\*\*S\*\*](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29到**S**)1 3.write2到新的关注[`{ w: 1 }`](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern.)**P**new 4.read2与读取关注\[`"majority"`]\([https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")到\*\*S\*\*](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29到**S**)3 | 对于项目`A`，更新`qty`为`50`。 阅读项目`A`。对于`qty`小于或等于的项目`50`， 更新`restock`到`true`。阅读项目`A`。 |

![使用读关注本地和写关注1的具有两个主数据的数据状态](https://docs.mongodb.com/manual/_images/causal-rc-local-wc-1.svg)

|       |                                                             |
| ----- | ----------------------------------------------------------- |
| ❌自己写  | read2从**S**3读取数据，该数据仅反映write2之后的状态，而不反映write1 之后是write2的状态。 |
| ❌单调读  | read2从**S**3读取数据，该数据不反映read1之后的状态（即，较早的状态不反映read1读取的数据）。    |
| ❌单调写  | write2更新了**P**new数据，而不会反映write1之后的状态。                       |
| ❌写跟随读 | write2更新**P**new的数据，该数据不反映read1之后的状态（即，较早的状态不反映read1读取的数据）。 |

#### 读关注`"local"`和写关注`"majority"`

在因果一致的会话中使用读取关注\[`"local"`]\([https://docs.mongodb.com/manual/reference/read-concern-local/#readconcern."local")和写入关注](https://docs.mongodb.com/manual/reference/read-concern-local/#readconcern."local"%29和写入关注) \[`"majority"`]\([https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority")可提供以下因果一致性保证：](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority"%29可提供以下因果一致性保证：)

❌自己读 ❌单调读read单调写 ❌写跟随读

在某些情况下（但不一定在所有情况下），此组合可以满足所有四个因果一致性保证。

**方案6（“关注本地”和“关注多数”）**

在此过渡期间，因为只有`P`new才能完成与 写入有关的写入，所以客户机会话可以成功发出以下操作序列，但因果关系不一致：\[`{ w: "majority" }`]\(<https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority>")

| 序列                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 | 例                                                                              |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| 1.write1\[`"majority"`]\(<https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority>") 到 新的关注**P**new 2.read1>与读关心\[`"majority"`]\([https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")到\*\*S\*\*](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29到**S**)1 3.write2\[`"majority"`]\([https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority")到新的关注\*\*P\*\*](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority"%29到新的关注**P**)new 4.read2与读取关注\[`"majority"`]\([https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")到\*\*S\*\*](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29到**S**)3 | 对于项目`A`，更新`qty`为`50`。 阅读项目`A`。对于`qty`小于或等于的项目`50`， 更新`restock`到`true`。阅读项目`A`。 |

![使用读关注本地和写关注多数的两个主数据的状态](https://docs.mongodb.com/manual/_images/causal-rc-local-wc-majority.svg)

|           |                                                             |
| --------- | ----------------------------------------------------------- |
| ❌阅读自己的文章。 | read1从**S**1读取不反映write11后状态的数据。                             |
| ❌单调读。     | read2从**S**3读取数据，该数据不反映read1之后的状态（即，较早的状态不反映read1读取的数据）。    |
| ✅单调写      | write2更新**P**new数据，以反映write1之后的状态。                          |
| ❌写跟随阅读。   | write2更新**P**new的数据，该数据不反映read1之后的状态（即，较早的状态不反映read1读取的数据）。 |

译者：杨帅

校对：杨帅


# 分布式查询

**在本页面**

* [读取复制集的操作](#读取)
* [在复制集上进行写操作](#复制集写)
* [读取分片群集的操作](#读分片)
* [在分片群集上写操作](#分片写)

## 读取复制集的操作

默认情况下，客户端读取复制集的[主](https://docs.mongodb.com/master/reference/glossary/#term-primary)副本;但是，客户端可以指定一个[读首选项](https://docs.mongodb.com/master/core/read-preference/) ，以便对其他成员进行直接读操作。例如，客户端可以配置读取偏好，从二级或从最近的成员读取到:

* 减少多数据中心部署中的延迟，
* 通过分配高读取量（相对于写入量）来提高读取吞吐量，
* 执行备份操作，和/或
* 允许读取直到选择一个[新的主节点](https://docs.mongodb.com/manual/core/replica-set-high-availability/#replica-set-failover)。

![将操作读取到副本集。 默认读取首选项将读取路由到主数据库。 \`\`最近''的读取首选项会将读取路由到最近的成员。](https://docs.mongodb.com/manual/_images/replica-set-read-preference.bakedsvg.svg)

来自复制集的次要成员的读取操作可能无法反映主要数据库的当前状态。将读取操作定向到不同服务器的读取首选项可能会导致非单调读取。

\_在3.6版中进行了更改：\_从MongoDB 3.6开始，客户端可以使用[因果一致的](https://docs.mongodb.com/manual/core/read-isolation-consistency-recency/#causal-consistency)会话，这提供了各种保证，包括单调读取。

您可以基于每个连接或每个操作配置读取首选项。有关读取首选项或读取首选项模式的更多信息，请参见[读取首选项](https://docs.mongodb.com/manual/core/read-preference/)和 [读取首选项模式](https://docs.mongodb.com/manual/core/read-preference/#replica-set-read-preference-modes)。

## 在复制集上进行写操作

在[复制集](https://docs.mongodb.com/master/reference/glossary/#term-replica-set),中，所有的写操作都指向集合的[主](https://docs.mongodb.com/master/reference/glossary/#term-primary)节点。主服务器应用写操作并将操作记录在主服务器的操作日志或[oplog](https://docs.mongodb.com/master/reference/glossary/#term-oplog)上。oplog是对数据集的可重复操作序列。集合中的次要成员不断复制oplog，并在一个异步进程中将这些操作应用到自己身上。

![Diagram of default routing of reads and writes to the primary.](https://docs.mongodb.com/manual/_images/replica-set-read-write-operations-primary.bakedsvg.svg)

有关复制集和写入操作的更多信息，请参见[复制](https://docs.mongodb.com/manual/replication/)和 [写入问题](https://docs.mongodb.com/manual/reference/write-concern/)。

## 读取分片群集的操作

[分片集群](https://docs.mongodb.com/manual/reference/glossary/#term-sharded-cluster)允许您以一种对应用程序几乎透明的方式在[mongod](https://docs.mongodb.com/manual/reference/program/mongod/#bin.mongod)实例集群之间划分数据集。有关分片集群的概述，请参阅本手册的[分片](https://docs.mongodb.com/manual/sharding/)部分。

对于分片群集，应用程序向[mongos](https://docs.mongodb.com/manual/reference/program/mongos/#bin.mongos)与该群集关联的实例之一发出操作 。

![分片群集的示意图。](https://docs.mongodb.com/manual/_images/sharded-cluster.bakedsvg.svg)

当分片群集上的读取操作定向到特定分片时，效率最高。分片集合的查询应包含集合的分片[键](https://docs.mongodb.com/manual/core/sharding-shard-key/#sharding-shard-key)。当查询包含分片键时，[`mongos`](https://docs.mongodb.com/manual/reference/program/mongos/#bin.mongos)可以使用[配置数据库中的](https://docs.mongodb.com/manual/core/sharded-cluster-config-servers/#sharding-config-server)群集元数据将查询路由到分片。

![将操作读取到分片群集。 查询条件包括分片键。 查询路由器\`\`mongos''可以将查询定位到适当的一个或多个分片。](https://docs.mongodb.com/manual/_images/sharded-cluster-targeted-query.bakedsvg.svg)

如果查询不包含分片键，则[`mongos`](https://docs.mongodb.com/manual/reference/program/mongos/#bin.mongos)必须将查询定向到集群中的\_所有分\_片。这些\_分散的收集\_查询可能效率很低。在较大的群集上，分散收集查询对于常规操作是不可行的。

![将操作读取到分片群集。 查询条件不包含分片键。 查询路由器\`\`mongos''必须向所有分片广播查询以进行收集。](https://docs.mongodb.com/manual/_images/sharded-cluster-scatter-gather-query.bakedsvg.svg)

对于复制集分片，从复制集的辅助成员进行的读取操作可能无法反映主副本的当前状态。将读取操作定向到不同服务器的读取首选项可能会导致非单调读取。

> **\[success] 注意**
>
> 从MongoDB 3.6开始，
>
> * 客户端可以使用[因果一致的](https://docs.mongodb.com/manual/core/read-isolation-consistency-recency/#causal-consistency) 会话，从而提供各种保证，包括单调读取。
> * 分片复制集的所有成员(不仅是主节点)都维护有关块元数据的元数据。如果不使用读取关注点，这将防止从辅助节点读取返回[孤立的数据](https://docs.mongodb.com/manual/reference/glossary/#term-orphaned-document)\[`"available"`]\([https://docs.mongodb.com/manual/reference/read-concern-available/#readconcern."available")。在较早的版本中，无论是否关注读操作，从辅助对象进行的读操作都可能返回孤立的文档。](https://docs.mongodb.com/manual/reference/read-concern-available/#readconcern."available"%29。在较早的版本中，无论是否关注读操作，从辅助对象进行的读操作都可能返回孤立的文档。)

有关分片群集中读取操作的更多信息，请参见 [mongos](https://docs.mongodb.com/manual/core/sharded-cluster-query-router/)和[Shard Keys](https://docs.mongodb.com/manual/core/sharding-shard-key/#sharding-shard-key) 部分。

## 在分片群集上写操作

对于[分片群集](https://docs.mongodb.com/master/reference/glossary/#term-sharded-cluster)中的分片集合，该 [`mongos`](https://docs.mongodb.com/manual/reference/program/mongos/#bin.mongos)指令将写操作从应用程序定向到负责数据集特定部分的分片。在[`mongos`](https://docs.mongodb.com/manual/reference/program/mongos/#bin.mongos)使用来自集群的元数据 的[配置数据库](https://docs.mongodb.com/manual/core/sharded-cluster-config-servers/#sharding-config-server)以路由写操作到适当的分片。

![分片群集的示意图。](https://docs.mongodb.com/manual/_images/sharded-cluster.bakedsvg.svg)

MongoDB根据[分片键](https://docs.mongodb.com/master/reference/glossary/#term-shard-key)的值将分片集合中的数据划分为范围。然后，MongoDB将这些块分配为分片。分片键决定块到分片的分布。这可能会影响集群中的写操作的性能。

![分片键值空间划分成较小范围或块的图。](https://docs.mongodb.com/manual/_images/sharding-range-based.bakedsvg.svg)

> **\[warning] 重要**
>
> 影响\_单个\_文档的 更新操作**必须**包含[分片键](https://docs.mongodb.com/master/reference/glossary/#term-shard-key) 或`_id` 字段。如果具有[分片键](https://docs.mongodb.com/manual/reference/glossary/#term-shard-key)，则影响多个文档的更新在某些情况下会更有效，但可以广播到所有分片。

如果分片键的值在每次插入时增加或减少，则所有插入操作都将针对单个分片。结果，单个分片的容量成为分片簇的插入容量的限制。

欲了解更多信息，请参阅[分片](https://docs.mongodb.com/manual/sharding/)和 [批量写入操作](https://docs.mongodb.com/manual/core/bulk-write-operations/)。

​ 也可以看看：

​ [可重试写入](https://docs.mongodb.com/manual/core/retryable-writes/#retryable-writes)

译者：杨帅

校对：杨帅


# 通过findAndModify进行线性化读取

## 概述

从复制集读取数据时，可能会读取过时(即可能并不能反映所有写道,发生前读操作)或不持久(即数据可能反映了写的状态还没有得到多数或复制集成员因此可以回滚)的数据，这取决于所使用的读取关注点。

从3.4版本开始，MongoDB引入了\[可线性化]\([https://docs.mongodb.com/master/reference/read-concern-linearizable/#readconcern."linearizable")的读关注点，它返回的是持久的数据，不会过时。\[可线性化\](https://docs.mongodb.com/master/reference/read-concern-linearizable/#readconcern."linearizable")的读关注保证仅适用于读操作指定了唯一标识单个文档的查询筛选器。](https://docs.mongodb.com/master/reference/read-concern-linearizable/#readconcern."linearizable"%29的读关注点，它返回的是持久的数据，不会过时。\[可线性化]%28https://docs.mongodb.com/master/reference/read-concern-linearizable/#readconcern."linearizable"%29的读关注保证仅适用于读操作指定了唯一标识单个文档的查询筛选器。)

本教程概述了一个替代过程，对于使用MongoDB 3.2的部署，该过程使用[`db.collection.findAndModify()`](https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/#db.collection.findAndModify)来读取不过时且不能回滚的数据。对于MongoDB 3.4，尽管可以应用概述的过程，但请参阅\[“线性化”]\(\[[https://docs.mongodb.com/manual/reference/read-concern-linearizable/#readconcern.%22linearizable%22\](https://docs.mongodb.com/manual/reference/read-concern-linearizable/#readconcern."linearizable"))阅读问题。](https://docs.mongodb.com/manual/reference/read-concern-linearizable/#readconcern.%22linearizable%22]%28https://docs.mongodb.com/manual/reference/read-concern-linearizable/#readconcern."linearizable"%29%29阅读问题。)

## 可线性通过findAndModify读取

此过程用于[`db.collection.findAndModify()`](https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/#db.collection.findAndModify)读取不过期且无法回滚的数据。为此，该过程使用[`findAndModify()`](https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/#db.collection.findAndModify)具有[写关注](https://docs.mongodb.com/manual/reference/write-concern/#write-concern)的方法来修改文档中的伪字段。具体来说，该过程要求：

* [`db.collection.findAndModify()`](https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/#db.collection.findAndModify)使用**完全**匹配查询，并且**必须存在**[唯一索引](https://docs.mongodb.com/manual/core/index-unique/) **才能**满足该查询。
* [`findAndModify()`](https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/#db.collection.findAndModify)必须实际修改文档；即导致文档更改。
* [`findAndModify()`](https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/#db.collection.findAndModify)必须使用写关注 。\[`{ w: "majority" }`]\(<https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority>")

> **\[warning] 重要**
>
> “仲裁读取”过程比单纯使用读取问题要花费大量成本，\[`"majority"`]\([https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority")因为它会导致写入延迟而不是读取延迟。仅在绝对不过期的情况下才应使用此技术。](https://docs.mongodb.com/manual/reference/read-concern-majority/#readconcern."majority"%29因为它会导致写入延迟而不是读取延迟。仅在绝对不过期的情况下才应使用此技术。)

### 前提条件

本教程从名为**products**的集合中读取内容。使用以下操作初始化集合。

```
db.products.insert( [
   {
     _id: 1,
     sku: "xyz123",
     description: "hats",
     available: [ { quantity: 25, size: "S" }, { quantity: 50, size: "M" } ],
     _dummy_field: 0
   },
   {
     _id: 2,
     sku: "abc123",
     description: "socks",
     available: [ { quantity: 10, size: "L" } ],
     _dummy_field: 0
   },
   {
     _id: 3,
     sku: "ijk123",
     description: "t-shirts",
     available: [ { quantity: 30, size: "M" }, { quantity: 5, size: "L" } ],
     _dummy_field: 0
   }
] )
```

该集合中的文档包含一个虚拟字段`_dummy_field`，该字段 [`db.collection.findAndModify()`](https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/#db.collection.findAndModify)在本教程中将通过递增 。如果该字段不存在，则该[`db.collection.findAndModify()`](https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/#db.collection.findAndModify)操作会将字段添加到文档中。该字段的目的是确保[`db.collection.findAndModify()`](https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/#db.collection.findAndModify)对文档进行修改。

### 程序

#### 1.创建一个唯一索引。

在将用于指定[`db.collection.findAndModify()`](https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/#db.collection.findAndModify)操作中完全匹配的字段上创建唯一索引。

本教程将在`sku`现场使用完全匹配。这样，在`sku`字段上创建唯一索引。

```
db.products.createIndex( { sku: 1 }, { unique: true } )
```

#### 2.使用`findAndModify`读取提交的数据。

使用该[`db.collection.findAndModify()`](https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/#db.collection.findAndModify)方法对要阅读的文档进行简单更新，然后返回修改后的文档。需要写关注。要指定要阅读的文档，必须使用唯一索引支持的完全匹配查询。\[`{ w: "majority" }`]\(<https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority>")

下面的[`findAndModify()`](https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/#db.collection.findAndModify)操作在唯一索引的字段`sku`上指定精确匹配，并增加匹配文档中名为`_dummy_field`的字段。虽然不是必需的，但该命令的写操作还包括一个5000毫秒的[`wtimeout`](https://docs.mongodb.com/manual/reference/write-concern/#wc-wtimeout)值，以防止在写操作不能传播到大多数投票成员时永远阻塞操作。

```
var updatedDocument = db.products.findAndModify(
   {
     query: { sku: "abc123" },
     update: { $inc: { _dummy_field: 1 } },
     new: true,
     writeConcern: { w: "majority", wtimeout: 5000 }
   }
);
```

即使在副本集中的两个节点认为它们是主节点的情况下，也只有一个节点能够用\[`w: "majority"`]\([https://docs.mongodb.com/master/reference/write-concern/#writeconcern."majority").完成写操作。因此，只有当客户机连接到真正的主服务器来执行操作时，具有\[“多数”\](https://docs.mongodb.com/master/reference/write-concern/#writeconcern."majority")写关注点的\[\`findAndModify()\`\](https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/#db.collection.findAndModify)方法才会成功。](https://docs.mongodb.com/master/reference/write-concern/#writeconcern."majority"%29.完成写操作。因此，只有当客户机连接到真正的主服务器来执行操作时，具有\[“多数”]%28https://docs.mongodb.com/master/reference/write-concern/#writeconcern."majority"%29写关注点的\[`findAndModify%28%29`]%28https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/#db.collection.findAndModify%29方法才会成功。)

由于仲裁读取过程只会增加文档中的虚拟字段，因此您可以安全地重复调用 [`findAndModify()`](https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/#db.collection.findAndModify)，根据需要调整 [wtimeout](https://docs.mongodb.com/manual/reference/write-concern/#wc-wtimeout)。

译者：杨帅

校对：杨帅


# 查询计划

**在本页面**

* [计划缓存条目状态](#计划)
* [`queryHash`](#queryHash)
* [`planCacheKey`](#planCacheKey)
* [可用性](#可用性)

对于查询，MongoDB查询优化器在给定可用索引的情况下选择并缓存效率最高的查询计划。最有效的查询计划的评估是基于查询执行计划在查询计划评估候选计划时执行的“工作单元”(**works**)的数量。

关联的计划缓存条目用于具有相同查询形状的后续查询。

## 计划缓存条目状态

从MongoDB 4.2开始，缓存条目与状态关联：

| State                                                                         | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| ----------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [失踪](https://docs.mongodb.com/manual/core/query-plans/#cache-entry-missing)   | 缓存中不存在此形状的条目。 对于查询，如果形状的缓存条目状态为 [Missing](https://docs.mongodb.com/manual/core/query-plans/#cache-entry-missing)： 1.对候选计划进行评估并选出一个获胜的计划。 2.所选计划将以非活动状态及其工作值添加到缓存中。。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| [不活跃](https://docs.mongodb.com/manual/core/query-plans/#cache-entry-inactive) | 缓存中的条目是此形状的占位符条目。也就是说，计划者已经看到了形状并计算了其成本（`works`价值）并存储为占位符条目，但查询形状**不**用于生成查询计划。 对于查询，如果形状的缓存条目状态非[活动](https://docs.mongodb.com/manual/core/query-plans/#cache-entry-inactive)： 1.对候选计划进行评估并选出一个获胜的计划。 2.所选计划的工作值与非活动条目的工作值进行比较。如果所选计划的works值为：小于或等于[非活动](https://docs.mongodb.com/manual/core/query-plans/#cache-entry-inactive)条目的， 所选计划将替换占位符“不 [活动”](https://docs.mongodb.com/manual/core/query-plans/#cache-entry-inactive)条目，并具有“ [活动”](https://docs.mongodb.com/manual/core/query-plans/#cache-entry-active)状态。 如果在替换发生之前，“ [非活动”](https://docs.mongodb.com/manual/core/query-plans/#cache-entry-inactive)条目变为“ [活动”](https://docs.mongodb.com/manual/core/query-plans/#cache-entry-active)(例如，由于其他查询操作)，则仅当新活动条目的`works`值大于所选计划时，才会替换该新活动条目。 大于非[活动](https://docs.mongodb.com/manual/core/query-plans/#cache-entry-inactive)条目的数量， 不[活动](https://docs.mongodb.com/master/core/query-plans/#cache-entry-inactive)的条目仍然存在，但其工作值增加。 |
| [活性](https://docs.mongodb.com/manual/core/query-plans/#cache-entry-active)    | 缓存中的条目用于中奖计划。计划者可以使用该条目来生成查询计划。 对于查询，如果形状的缓存条目状态为 [Active](https://docs.mongodb.com/manual/core/query-plans/#cache-entry-active)： 活动条目用于生成查询计划。 计划者还评估条目的性能，如果条目的 `works`值不再符合选择标准，它将转换为非[活动](https://docs.mongodb.com/manual/core/query-plans/#cache-entry-inactive)状态。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |

有关触发对计划缓存进行更改的其他方案，请参阅[计划缓存刷新](https://docs.mongodb.com/manual/core/query-plans/#query-plans-plan-cache-flushes)。

### 查询计划和高速缓存信息

要查看给定查询的查询计划信息，可以使用 [`db.collection.explain()`](https://docs.mongodb.com/manual/reference/method/db.collection.explain/#db.collection.explain)或[`cursor.explain()`](https://docs.mongodb.com/manual/reference/method/cursor.explain/#cursor.explain)。

从MongoDB 4.2开始，您可以使用[`$planCacheStats`](https://docs.mongodb.com/manual/reference/operator/aggregation/planCacheStats/#pipe._S_planCacheStats) 聚合阶段来查看集合的计划缓存信息。

### 计划缓存刷新

如果[`mongod`](https://docs.mongodb.com/manual/reference/program/mongod/#bin.mongod) 重新启动或关闭，查询计划缓存将不会保留。此外：

* 索引或收集删除之类的目录操作会清除计划缓存。
* 最近最少使用（LRU）高速缓存替换机制将清除最近最少访问的高速缓存条目，而不管其状态如何。

用户还可以：

* 使用[`PlanCache.clear()`](https://docs.mongodb.com/manual/reference/method/PlanCache.clear/#PlanCache.clear)方法手动清除整个计划缓存 。
* 使用[`PlanCache.clearPlansByQuery()`](https://docs.mongodb.com/manual/reference/method/PlanCache.clearPlansByQuery/#PlanCache.clearPlansByQuery)方法手动清除特定的计划缓存条目 。

  也可以看看

  [queryHash和planCacheKey](https://docs.mongodb.com/manual/core/query-plans/#query-hash-plan-cache-key)

#### queryHash和planCacheKey

## queryHash

为了帮助识别具有相同[查询形状](https://docs.mongodb.com/manual/reference/glossary/#term-query-shape)的慢速查询，从MongoDB 4.2开始，每个查询形状都与一个[queryHash](https://docs.mongodb.com/manual/release-notes/4.2/#query-hash)相关联。**queryHash**是一个十六进制字符串，表示查询形状的散列，并且只依赖于查询形状。

> **\[success] 注意**
>
> 与任何hash函数一样，两个不同的查询形状可能会导致相同的hash值。但是，不同查询形状之间不会发生哈希冲突。

## planCacheKey

为了更深入地了解[缓存查询计划](https://docs.mongodb.com/master/core/query-plans/#)，MongoDB 4.2引入了 [planCacheKey](https://docs.mongodb.com/master/release-notes/4.2/#plan-cache-key).

`planCacheKey` 是与查询关联的计划缓存条目的键的hash值。

> **\[success] 注意**
>
> 与**queryHash**不同，**planCacheKey**是查询形状和当前可用的形状索引的函数。也就是说，如果添加/删除了支持查询形状的索引，**planCacheKey**值可能会改变，而**queryHash**值不会改变。

例如，考虑一个具有以下索引的**foo**集合:

```
db.foo.createIndex( { x: 1 } )
db.foo.createIndex( { x: 1, y: 1 } )
db.foo.createIndex( { x: 1, z: 1 }, { partialFilterExpression: { x: { $gt: 10 } } } )
```

集合上的以下查询具有相同的形状:

```
db.foo.explain().find( { x: { $gt: 5 } } )  // Query Operation 1
db.foo.explain().find( { x: { $gt: 20 } } ) // Query Operation 2
```

对于这些查询，带有[部分过滤表达式](https://docs.mongodb.com/master/core/index-partial/#partial-index-query-coverage) 的索引可以支持查询操作2，但不支持查询操作1。由于支持查询操作1的索引与查询操作2不同，这两个查询具有不同的**planCacheKey**。

如果删除了其中一个索引，或者添加了一个新的索引\*\*{x: 1, a: 1}**，那么用于这两个查询操作的**planCacheKey\*\*将会改变。

## 可用性

**queryHash**和**planCacheKey**是可用的在:

* [explain() output](https://docs.mongodb.com/manual/reference/explain-results/)字段： [`queryPlanner.queryHash`](https://docs.mongodb.com/manual/reference/explain-results/#explain.queryPlanner.queryHash)和 [`queryPlanner.planCacheKey`](https://docs.mongodb.com/manual/reference/explain-results/#explain.queryPlanner.planCacheKey)
* 记录慢查询时，[探查器日志消息](https://docs.mongodb.com/manual/tutorial/manage-the-database-profiler/) 和[诊断日志消息（即mongod / mongos日志消息）](https://docs.mongodb.com/manual/reference/log-messages/)。
* [`$planCacheStats`](https://docs.mongodb.com/manual/reference/operator/aggregation/planCacheStats/#pipe._S_planCacheStats)聚合阶段（*MongoDB 4.2中的新增功能*）
* \*\*PlanCache.listQueryShapes()\*\*方法/**planCacheListQueryShapes**命令
* \*\*PlanCache.getPlansByQuery()\*\*方法/**planCacheListPlans**命令

#### 索引筛选器

索引筛选器确定优化器为查询形状评估哪些索引。查询形状由查询、排序和投影规范的组合组成。如果存在针对给定查询形状的索引筛选器，则优化器仅考虑筛选器中指定的那些索引。

当存在查询形状的索引过滤器时，MongoDB会忽略[`hint()`](https://docs.mongodb.com/manual/reference/method/cursor.hint/#cursor.hint)。要查看MongoDB是否为查询形状应用了索引筛选器，请检查[`db.collection.explain()`](https://docs.mongodb.com/master/reference/method/db.collection.explain/#db.collection.explain)或[`cursor.explain()`](https://docs.mongodb.com/master/reference/method/cursor.explain/#cursor.explain) 方法的[`indexFilterSet`](https://docs.mongodb.com/master/reference/explain-results/#explain.queryPlanner.indexFilterSet)字段。

索引过滤器仅影响优化器评估的索引；对于给定的查询形状，优化器仍然可以选择将集合扫描作为获胜计划。

索引过滤器在服务器进程的持续时间内存在，并且在关闭后不会持续存在。MongoDB还提供了手动删除过滤器的命令。

因为索引过滤器会覆盖优化器和[`hint()`](https://docs.mongodb.com/manual/reference/method/cursor.hint/#cursor.hint)方法的预期行为，所以请谨慎使用索引过滤器。

见[`planCacheListFilters`](https://docs.mongodb.com/manual/reference/command/planCacheListFilters/#dbcmd.planCacheListFilters)， [`planCacheClearFilters`](https://docs.mongodb.com/manual/reference/command/planCacheClearFilters/#dbcmd.planCacheClearFilters)和[`planCacheSetFilter`](https://docs.mongodb.com/manual/reference/command/planCacheSetFilter/#dbcmd.planCacheSetFilter)。

​ 也可以看看：

​ [索引策略](https://docs.mongodb.com/manual/applications/indexes/)

译者：杨帅

校对：杨帅


# 查询优化

**在本页面**

* [创建索引以支持读取操作](#创建)
* [查询选择性](#查询)
* [覆盖查询](#覆盖)

索引通过减少查询操作需要处理的数据量来提高读操作的效率。这简化了与在MongoDB中完成查询相关的工作。

## 创建索引以支持读取操作

如果应用程序查询特定字段或字段集上的集合，那么查询字段上的[索引](https://docs.mongodb.com/manual/core/index-compound/)或字段集上的[复合索引](https://docs.mongodb.com/manual/core/index-compound/)可以防止查询扫描整个集合来查找和返回查询结果。有关索引的更多信息，请参阅[MongoDB中索引中完整文档](https://docs.mongodb.com/manual/indexes/)。

**例子**

应用程序查询类型字段上的库存集合。类型字段的值是用户驱动的。

```
var typeValue = <someUserInput>;
db.inventory.find( { type: typeValue } );
```

要提高此查询的性能，请向**type**字段上的**inventory**集合添加升序或降序索引。在[`mongo`](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) shell中，您可以使用[`db.collection.createIndex()`](https://docs.mongodb.com/manual/reference/method/db.collection.createIndex/#db.collection.createIndex)方法创建索引:

```
db.inventory.createIndex( { type: 1 } )
```

这个索引可以防止上述类型查询扫描整个集合返回结果。

要使用索引[分析查询的性能](https://docs.mongodb.com/manual/tutorial/analyze-query-plan/)，请参阅 [分析查询性能](https://docs.mongodb.com/manual/tutorial/analyze-query-plan/)。

除了优化读取操作外，索引还可以支持排序操作并允许更有效地利用存储。有关索引创建的更多信息，请参见 [`db.collection.createIndex()`](https://docs.mongodb.com/manual/reference/method/db.collection.createIndex/#db.collection.createIndex)和 [索引](https://docs.mongodb.com/manual/indexes/)。

**对于单字段索引，升序和降序之间的选择并不重要。对于复合索引，选择很重要。有关更多详细信息，请参见**[**索引顺序**](https://docs.mongodb.com/manual/core/index-compound/#index-ascending-and-descending)**。**

## 查询选择性

查询选择性指的是查询谓词排除或过滤集合中的文档的能力。查询选择性可以决定查询是否能够有效地使用索引，甚至根本不使用索引。

选择性更强的查询匹配的文档比例更小。例如，唯一\*\*\_id\*\*字段上的相等匹配具有很高的选择性，因为它最多只能匹配一个文档。

选择性较低的查询匹配较大比例的文档。选择性较低的查询不能有效地使用索引，甚至根本不能使用索引。

例如，不等操作符[`$nin`](https://docs.mongodb.com/manual/reference/operator/query/nin/#op._S_nin)和 [`$ne`](https://docs.mongodb.com/manual/reference/operator/query/ne/#op._S_ne)的选择性不是很强，因为它们通常匹配索引的很大一部分。因此，在许多情况下，带有索引的[`$nin`](https://docs.mongodb.com/manual/reference/operator/query/nin/#op._S_nin)或 [`$ne`](https://docs.mongodb.com/manual/reference/operator/query/ne/#op._S_ne)查询的执行性能可能不比必须扫描集合中所有文档的[`$nin`](https://docs.mongodb.com/manual/reference/operator/query/nin/#op._S_nin)或 [`$ne`](https://docs.mongodb.com/manual/reference/operator/query/ne/#op._S_ne)查询好。

正则表达式的选择性取决于表达式本身。有关详细信息，请参见[正则表达式和索引使用](https://docs.mongodb.com/manual/reference/operator/query/regex/#regex-index-use)。[`regular expressions`](https://docs.mongodb.com/manual/reference/operator/query/regex/#op._S_regex)

## 覆盖查询

覆盖查询是可以使用索引完全满足而不需要检查任何文档的查询。当下列所有情况都适用时，索引将 [覆盖](https://docs.mongodb.com/manual/core/query-optimization/#indexes-covered-queries)查询：

* [查询](https://docs.mongodb.com/manual/tutorial/query-documents/#read-operations-query-document) 中的所有字段都是索引的一部分。
* 结果中返回的所有字段都在同一索引中。
* 查询中没有字段等于`null`(即\*\*{“field”:null}**或**{“field”:{$eq: null}}\*\*)。

例如，一个集合`inventory`在`type`和`item`字段上具有以下索引 ：

```
db.inventory.createIndex( { type: 1, item: 1 } )
```

该索引将涵盖以下操作，该操作在`type`和`item`字段上查询 并仅返回该`item`字段：

```
db.inventory.find(
   { type: "food", item:/^c/ },
   { item: 1, _id: 0 }
)
```

为了让指定的索引覆盖查询，投影文档必须显式地指定\*\*\_id: 0**来从结果中排除**\_id**字段，因为索引不包括**\_id\*\*字段。

3.6版本的改变:索引可以覆盖对嵌入文档中的字段的查询。

例如，考虑一个**userdata**集合，它具有以下形式的文档:

```
{ _id: 1, user: { login: "tester" } }
```

该集合具有以下索引：

```
{ "user.login": 1 }
```

该索引将涵盖以下查询：`{ "user.login": 1 }`

```
db.userdata.find( { "user.login": "tester" }, { "user.login": 1, _id: 0 } )
```

**要为嵌入式文档中的字段建立索引，请使用**[**点符号**](https://docs.mongodb.com/manual/reference/glossary/#term-dot-notation)**。**

### 多键覆盖

从3.6开始，如果索引跟踪哪个或哪个字段导致索引为多键，那么多键索引可以覆盖对非数组字段的查询。在MongoDB 3.4或更高版本的存储引擎(MMAPv1除外)上创建的多键索引跟踪该数据。

[多键索引](https://docs.mongodb.com/manual/core/index-multikey/#index-type-multikey)不能覆盖对数组字段的查询。

### 性能

因为索引包含查询所需的所有字段，所以MongoDB既可以匹配[查询条件](https://docs.mongodb.com/manual/tutorial/query-documents/#read-operations-query-document) ，又可以仅使用索引返回结果。

仅查询索引要比查询索引之外的文档快得多。索引键通常比它们编目的文档小，索引通常在RAM中可用，或按顺序位于磁盘上。

### 局限性

#### 索引字段的限制

* [地理空间索引](https://docs.mongodb.com/manual/geospatial-queries/#index-feature-geospatial)不能 [覆盖查询](https://docs.mongodb.com/manual/core/query-optimization/#covered-queries)。
* [多键索引](https://docs.mongodb.com/manual/core/index-multikey/#index-type-multikey)不能覆盖对数组字段的查询。

  也可以看看

  [多键覆盖](https://docs.mongodb.com/manual/core/query-optimization/#multikey-covering)

#### 分片集合的限制

在MongoDB中3.0开始，索引不能覆盖在查询 [分片](https://docs.mongodb.com/manual/reference/glossary/#term-shard)的时候对一个运行集合 [`mongos`](https://docs.mongodb.com/manual/reference/program/mongos/#bin.mongos)，如果指数不包含片键，除了具有以下不同的`_id`指标：如果在分片集合的查询只规定了一个条件`_id`字段并仅返回该`_id`字段，即使该 字段不是分片键，`_id`索引也可以覆盖针对[`mongos`](https://docs.mongodb.com/manual/reference/program/mongos/#bin.mongos)该`_id`字段的查询。

在以前的版本中，在对[`mongos`](https://docs.mongodb.com/manual/reference/program/mongos/#bin.mongos)运行时，索引不能[覆盖](https://docs.mongodb.com/manual/core/query-optimization/#covered-queries) 对[分片](https://docs.mongodb.com/manual/reference/glossary/#term-shard)集合的查询。

### 解释

要确定查询是否为覆盖查询，请使用 [`db.collection.explain()`](https://docs.mongodb.com/manual/reference/method/db.collection.explain/#db.collection.explain)或[`explain()`](https://docs.mongodb.com/manual/reference/method/cursor.explain/#cursor.explain) 方法，然后查看[结果](https://docs.mongodb.com/manual/reference/explain-results/#explain-output-covered-queries)。

[`db.collection.explain()`](https://docs.mongodb.com/manual/reference/method/db.collection.explain/#db.collection.explain)提供有关其他操作执行的信息，例如[`db.collection.update()`](https://docs.mongodb.com/manual/reference/method/db.collection.update/#db.collection.update)。有关[`db.collection.explain()`](https://docs.mongodb.com/manual/reference/method/db.collection.explain/#db.collection.explain)详细信息，请参见 。

有关更多信息，请参见[度量索引使用](https://docs.mongodb.com/manual/tutorial/measure-index-use/#indexes-measuring-use)。

译者：杨帅

校对：杨帅


# 评估当前操作性能

**在本页面**

* [使用数据库分析器来计算针对数据库的操作](#操作)
* [使用`db.currentOp()`来评估`mongod`业务](#业务)
* [使用`explain`来评估查询性能](#性能)

以下各节介绍了用于评估操作性能的技术。

## 使用数据库分析器来计算针对数据库的操作

MongoDB提供了一个[数据库分析器](https://docs.mongodb.com/manual/tutorial/manage-the-database-profiler/)，它显示针对数据库的每个操作的性能特征。使用分析器定位任何运行缓慢的查询或写操作。例如，您可以使用此信息来确定要创建什么索引。

从MongoDB 4.2开始，用于读写操作的[profiler条目](https://docs.mongodb.com/manual/tutorial/manage-the-database-profiler/)和诊断日志消息(即**mongod/mongos日志消息**)包括:

* `queryHash`帮助识别具有相同[查询形状的](https://docs.mongodb.com/manual/reference/glossary/#term-query-shape)慢速查询 。
* `planCacheKey`为深入了解[查询计划缓存](https://docs.mongodb.com/manual/core/query-plans/)提供慢速查询。

从版本4.2(也可以从4.0.6开始使用)开始，复制集的次要成员现在会记录花费超过慢操作阈值的**oplog条目**。这些缓慢的**oplog**消息被记录在REPL组件下的诊断日志中，并应用文本**op: 取<`num`>ms**。这些较慢的oplog条目仅依赖于较慢的操作阈值。它们不依赖于日志级别(系统或组件级别)、分析级别或较慢的操作采样率。分析器不会捕获很慢的**oplog**条目。

有关更多信息，请参见[Database Profiler](https://docs.mongodb.com/manual/tutorial/manage-the-database-profiler/)。

## 使用`db.currentOp()`到评估`mongod`业务

该[`db.currentOp()`](https://docs.mongodb.com/manual/reference/method/db.currentOp/#db.currentOp)方法报告[`mongod`](https://docs.mongodb.com/manual/reference/program/mongod/#bin.mongod)实例上正在运行的当前操作。

## 使用`explain`来评估查询性能

在[`cursor.explain()`](https://docs.mongodb.com/manual/reference/method/cursor.explain/#cursor.explain)与[`db.collection.explain()`](https://docs.mongodb.com/manual/reference/method/db.collection.explain/#db.collection.explain) 方法返回关于查询执行的信息，如MongoDB的选择以满足查询和执行统计数据的指标。您可以在[queryPlanner](https://docs.mongodb.com/manual/reference/method/db.collection.explain/#explain-method-queryplanner) 模式，[executionStats](https://docs.mongodb.com/manual/reference/method/db.collection.explain/#explain-method-executionstats)模式或 [allPlansExecution](https://docs.mongodb.com/manual/reference/method/db.collection.explain/#explain-method-allplansexecution)模式下运行这些方法，以控制返回的信息量。

<https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo>)

**例子**

要在名为**records**的集合中查询与表达式\*\*{a: 1}\*\*匹配的文档时使用[`cursor.explain()`](https://docs.mongodb.com/manual/reference/method/cursor.explain/#cursor.explain)，在mongo shell中使用类似于下面的操作:

```
db.records.find( { a: 1 } ).explain("executionStats")
```

从MongoDB 4.2开始，**explain**输出包括:

* [`queryHash`](https://docs.mongodb.com/manual/reference/explain-results/#explain.queryPlanner.queryHash)帮助识别具有相同[查询形状的](https://docs.mongodb.com/manual/reference/glossary/#term-query-shape)慢速查询。
* [`planCacheKey`](https://docs.mongodb.com/manual/reference/explain-results/#explain.queryPlanner.planCacheKey)为深入了解[查询计划缓存](https://docs.mongodb.com/manual/core/query-plans/)提供慢速查询。

欲了解更多信息，请参阅[解释结果](https://docs.mongodb.com/manual/reference/explain-results/)， [`cursor.explain()`](https://docs.mongodb.com/manual/reference/method/cursor.explain/#cursor.explain)，[`db.collection.explain()`](https://docs.mongodb.com/manual/reference/method/db.collection.explain/#db.collection.explain)，和 [分析查询性能](https://docs.mongodb.com/manual/tutorial/analyze-query-plan/)。

译者：杨帅

校对：杨帅


# 优化查询性能

**在本页面**

* [创建索引以支持查询](#1)
* [限制查询结果数以减少网络需求](#2)
* [使用投影仅返回必要的数据](#3)
* [使用`$hint`选择一个特定的索引](#4)
* [使用增量运算符在服务器端执行操作](#5)

## 创建索引以支持查询

对于常见的查询，请创建[索引](https://docs.mongodb.com/manual/indexes/)。如果一个查询搜索多个字段，请创建一个[复合索引](https://docs.mongodb.com/manual/core/index-compound/#index-type-compound)。扫描索引比扫描集合快得多。索引结构小于文档参考，并按顺序存储参考。

> **例子**
>
> 如果你有一个包含博客帖子的帖子集合，并且你经常发出一个查询，对`author_name`字段排序，那么你可以通过在`author_name`字段上创建一个索引来优化查询:
>
> ```
> db.posts.createIndex( { author_name : 1 } )
> ```

索引还可以提高对给定字段进行常规排序的查询的效率。

> **例子**
>
> 如果您定期发出查询排序的`timestamp`字段，然后您可以优化查询创建一个索引的`timestamp`字段:
>
> 创建此索引：
>
> ```
> db.posts.createIndex( { timestamp : 1 } )
> ```
>
> 优化此查询：
>
> ```
> db.posts.find().sort( { timestamp : -1 } )
> ```

因为MongoDB可以按升序和降序读取索引，所以单键索引的方向并不重要。

索引支持查询，更新操作以及[聚合管道的](https://docs.mongodb.com/manual/core/aggregation-pipeline/#aggregation-pipeline-operators-and-performance)某些阶段 。

在以下情况下，`BinData`更有效地将类型为索引的键存储在索引中：

* 二进制子类型的值在0-7或128-135的范围内，并且
* 字节数组的长度为：0、1、2、3、4、5、6、7、8、10、12、14、16、20、24或32。

## 限制查询的结果数以减少网络需求

MongoDB [游标](https://docs.mongodb.com/manual/reference/glossary/#term-cursor)以多个文档为一组返回结果。如果知道所需结果的数量，则可以通过发出该[`limit()`](https://docs.mongodb.com/manual/reference/method/cursor.limit/#cursor.limit) 方法来减少对网络资源的需求。

这通常与排序操作结合使用。例如，如果您只需要从查询到`posts` 集合的10个结果，则可以发出以下命令：

```
db.posts.find().sort( { timestamp : -1 } ).limit(10)
```

有关限制结果的更多信息，请参见 [`limit()`](https://docs.mongodb.com/manual/reference/method/cursor.limit/#cursor.limit)

## 使用投影仅返回必要的数据

当您仅需要文档中字段的子集时，可以通过仅返回所需的字段来获得更好的性能：

例如，如果在查询中的`posts`集合，你只需要`timestamp`，`title`，`author`，和`abstract`领域，你会发出以下命令：

复制复制的

```
db 。职位。find （ {}， {  timestamp  ： 1  ， title  ： 1  ， author  ： 1  ， abstract  ： 1 }  ）。排序（ {  时间戳 ： - 1  }  ）
```

有关使用投影的更多信息，请参见 [要从查询返回的项目字段](https://docs.mongodb.com/manual/tutorial/project-fields-from-query-results/#read-operations-projection)。

## 使用`$hint`选择一个特定的指数

在大多数情况下，[查询优化器](https://docs.mongodb.com/manual/core/query-plans/#read-operations-query-optimization)为特定操作选择最佳索引。但是，您可以使用[`hint()`](https://docs.mongodb.com/manual/reference/method/cursor.hint/#cursor.hint)方法强制MongoDB使用特定索引。使用 [`hint()`](https://docs.mongodb.com/manual/reference/method/cursor.hint/#cursor.hint)以支持性能测试，或在某些查询，您必须选择包含在几个索引中的一个或多个字段。

## 使用增量运算符在服务器端执行操作

使用MongoDB的[`$inc`](https://docs.mongodb.com/manual/reference/operator/update/inc/#up._S_inc)操作符递增或递减文档中的值。操作符在服务器端增加字段的值，作为选择文档、在客户端进行简单修改然后将整个文档写入服务器的替代方法。[`$inc`](https://docs.mongodb.com/manual/reference/operator/update/inc/#up._S_inc)操作符还可以帮助避免竞争条件，当两个应用程序实例查询一个文档、手动增加一个字段并同时将整个文档保存回来时，可能会出现竞争条件。

译者：杨帅

校对：杨帅


# 写操作性能

**在本页面**

* [索引](#索引)
* [储存性能](#储存)

## 索引

集合上的每个索引都会给写操作的性能增加一些负担。

对于集合上的每个操作[`insert`](https://docs.mongodb.com/manual/reference/command/insert/#dbcmd.insert)或[`delete`](https://docs.mongodb.com/manual/reference/command/delete/#dbcmd.delete)写入操作，MongoDB从目标集合的每个索引中插入或删除相应的文档键。根据受[`update`](https://docs.mongodb.com/manual/reference/command/update/#dbcmd.update)影响的键，更新操作可能导致对集合上的索引子集进行更新。

> **\[success] 注意**
>
> 如果写操作中涉及的文档包含在索引中，则MongoDB仅更新[稀疏](https://docs.mongodb.com/manual/core/index-sparse/#index-type-sparse)索引或 [部分](https://docs.mongodb.com/manual/core/index-partial/#index-type-partial)索引。

一般来说，索引为读操作提供的性能收益抵得上插入损失。但是，为了尽可能优化写性能，在创建新索引和评估现有索引时要小心，以确保您的查询实际使用这些索引。

有关索引和查询，请参见[查询优化](https://docs.mongodb.com/manual/core/query-optimization/)。有关索引的更多信息，请参见[索引](https://docs.mongodb.com/manual/indexes/)和 [索引策略](https://docs.mongodb.com/manual/applications/indexes/)。

## 储存性能

### 硬件

存储系统的功能为MongoDB的写操作性能创建了一些重要的物理限制。与驱动器的存储系统相关的许多独特因素都会影响写入性能，包括随机访问模式，磁盘缓存，磁盘预读和RAID配置。

对于随机工作负载，固态驱动器（SSD）的性能可比旋转硬盘（HDD）高100倍或更多。

​ 请看:

​ [生产说明](https://docs.mongodb.com/manual/administration/production-notes/)中有关其他硬件和配置选项的建议。

### 日记

为了在崩溃时提供持久性，MongoDB使用预\_写日志记录\_到磁盘[日志上](https://docs.mongodb.com/manual/reference/glossary/#term-journal)。MongoDB首先将内存中的更改写入磁盘上的日志文件。如果MongoDB在对数据文件进行更改之前终止或遇到错误，MongoDB可以使用日志文件对数据文件应用写操作。

虽然日志提供的持久性保证通常超过了额外写操作的性能成本，但考虑一下日志和性能之间的以下交互:

* 如果日志和数据文件位于同一块设备上，则数据文件和日志可能必须竞争有限数量的可用I / O资源。将日志移动到单独的设备可能会增加写操作的容量。
* 如果应用程序指定了包括**J**选项的[写关注点](https://docs.mongodb.com/manual/reference/write-concern/)，mongod将减少日志写之间的持续时间，这会增加总体写负载。
* 日志写入之间的持续时间可以使用[`commitIntervalMs`](https://docs.mongodb.com/manual/reference/configuration-options/#storage.journal.commitIntervalMs)运行时选项进行配置 。减少日志提交之间的时间间隔将增加写入操作的数量，这可能会限制MongoDB的写入操作能力。增加日志提交之间的时间量可能会减少写操作的总数，但也会增加在发生故障的情况下日志不会记录写操作的机会。

有关日志记录的其他信息，请参见[日志记录](https://docs.mongodb.com/manual/core/journaling/)。

译者：杨帅

校对：杨帅


# 说明结果

**在本页面**

* [解释输出](#1)
  * [`queryPlanner`](#11)
  * [`executionStats`](#12)
  * [`serverInfo`](#13)
* [3.0格式变更](#2)
  * [集合扫描与索引使用](#21)
  * [覆盖查询](#22)
  * [索引交集](#23)
  * [`$or` 表达](#24)

为了返回查询计划的信息和查询计划的执行统计信息，MongoDB提供:

* [`db.collection.explain()`](https://docs.mongodb.com/manual/reference/method/db.collection.explain/#db.collection.explain)方法，
* [`cursor.explain()`](https://docs.mongodb.com/manual/reference/method/cursor.explain/#cursor.explain)方法，
* 该[`explain`](https://docs.mongodb.com/manual/reference/command/explain/#dbcmd.explain)命令。

`explain`结果将查询计划呈现为一个阶段树。

```
"winningPlan" : {
   "stage" : <STAGE1>,
   ...
   "inputStage" : {
      "stage" : <STAGE2>,
      ...
      "inputStage" : {
         "stage" : <STAGE3>,
         ...
      }
   }
},
```

每个阶段将其结果(即文档或索引键)传递给父节点。叶节点访问集合或索引。内部节点操作子节点产生的文档或索引键。根节点是MongoDB派生结果集的最后一个阶段。

阶段描述了操作；例如

* `COLLSCAN` 用于收集扫描
* `IXSCAN` 用于扫描索引键
* `FETCH` 用于检索文件
* `SHARD_MERGE` 用于合并分片的结果
* `SHARDING_FILTER` 用于从分片中筛选出孤立文档

## 解释输出

以下各节列出了该`explain`操作返回的一些关键字段。

> 注意
>
> * 字段列表并不意味着详尽无遗，而只是强调了早期解释版本中的一些关键字段更改。
> * 输出格式在各个发行版之间可能有所更改。

### `queryPlanner`

[`queryPlanner`](https://docs.mongodb.com/manual/reference/explain-results/#explain.queryPlanner)信息详细说明了[查询优化器](https://docs.mongodb.com/manual/core/query-plans/)选择的计划。

* 未分片集合
* 分片集合

**explain.queryPlanner**

包含有关[查询优化器](https://docs.mongodb.com/manual/core/query-plans/)选择查询计划的信息 。

* `explain.queryPlanner.``namespace`

  一个字符串，它指定`<database>.<collection>`要对其运行查询的名称空间（即 ）。
* `explain.queryPlanner.``indexFilterSet`

  一个布尔值，指定MongoDB是否对[查询形状](https://docs.mongodb.com/manual/reference/glossary/#term-query-shape)应用了[索引过滤器](https://docs.mongodb.com/manual/core/query-plans/#index-filters)。
* `explain.queryPlanner.``queryHash`

  一个十六进制字符串，代表[查询形状](https://docs.mongodb.com/manual/reference/glossary/#term-query-shape)的哈希， 并且仅取决于查询形状。 `queryHash`可以帮助识别具有相同查询形状的慢查询（包括写操作的查询过滤器）。

> 注意
>
> 与任何散列函数一样，两个不同的查询形状可能导致相同的散列值。但是，不同查询形状之间不太可能出现哈希冲突。

只有当值为**true**且仅应用于聚合管道操作中的explain时，该字段才会出现。当为**true**时，由于管道已被优化，所以在输出中不会出现聚合阶段信息。

*新版本4.2*

**explain.queryPlanner.winningPlan**

​ 详细说明查询优化器选择的计划的文档。MongoDB将计划呈现为一个阶段树;例如，一个阶段可以有一个**inputStage**，如果该阶段有 多个子阶段，则可以有**inputStage**。

​ **explain.queryPlanner.winningPlan.stage**

​ 表示舞台名称的字符串。

​ 每个阶段由特定于该阶段的信息组成。例如，**IXSCAN**阶段将包括索引边界以及特定于索引扫描的其他数据。如果一个阶段有一个子 阶段或多个子阶段，那么这个阶段将有一个inputStage或inputStage。

​ **explain.queryPlanner.winningPlan.inputStage**

​ 描述子阶段的文档，它向父阶段提供文档或索引键。如果父阶段只有一个子阶段，则会显示该字段。

​ **explain.queryPlanner.winningPlan.inputStages**

​ 一系列描述子阶段的文档。子阶段将文档或索引键提供给父阶段。\_如果\_父级具有多个子节点，\_则\_该字段存在。例如，[$或表达式的](https://docs.mongodb.com/manual/reference/explain-results/#explain-output-or-expression)阶 段或[索引交集](https://docs.mongodb.com/manual/reference/explain-results/#explain-output-index-intersection)会消耗来自多个源的输入。

​ **explain.queryPlanner.rejectedPlans**

​ 查询优化器考虑和拒绝的候选计划的数组。如果没有其他候选计划，则该数组可以为空。

### `executionStats`

返回的[`executionStats`](https://docs.mongodb.com/manual/reference/explain-results/#explain.executionStats)信息详细说明了获胜计划的执行情况。为了包括 `executionStats`在结果中，您必须在以下任一位置运行解释：

* [执行状态](https://docs.mongodb.com/manual/reference/method/db.collection.explain/#explain-method-executionstats)
* [allPlansExecution](https://docs.mongodb.com/manual/reference/method/db.collection.explain/#explain-method-allplansexecution) 详细模式。使用`allPlansExecution`模式包括在[计划选择](https://docs.mongodb.com/manual/core/query-plans/#query-plans-query-optimization)期间捕获的部分执行数据。
* 未分片集合
* 分片集合

**explain.executionStats.executionStages**

​ 以阶段树的形式详细说明获奖计划的完成执行情况；即一个阶段可以有一个`inputStage`或多个 `inputStages`。

​ **explain.executionStats.executionStages.works**

​ 指定查询执行阶段执行的“工作单位”的数量。查询执行将其工作分为几个小单元。“工作单元”可能包括检查单个索引键，从集合中获 取单个文档，对单个文档应用投影或进行内部簿记。

​ **explain.executionStats.executionStages.advanced**

​ 在此阶段返回到其父阶段的中间结果数，或将其\_前进\_。

​ **explain.executionStats.executionStages.needTime**

​ 没有将中间结果提前到其父阶段的工作周期数（请参阅参考资料 [`explain.executionStats.executionStages.advanced`](https://docs.mongodb.com/manual/reference/explain-results/#explain.executionStats.executionStages.advanced)）。例 如，索引扫描阶段可能会花费一个工作周期来寻找索引中的新位置，而不是返回索引键。

​ 这个工作周期将计入[`explain.executionStats.executionStages.needTime`](https://docs.mongodb.com/manual/reference/explain-results/#explain.executionStats.executionStages.needTime)而非计入

​ [`explain.executionStats.executionStages.advanced`](https://docs.mongodb.com/manual/reference/explain-results/#explain.executionStats.executionStages.advanced)。

​ **explain.executionStats.executionStages.needYield**

​ 存储层请求查询阶段挂起处理并产生其锁的次数。

​ **explain.executionStats.executionStages.saveState**

​ 查询阶段挂起处理并保存其当前执行状态的次数，例如，为准备产生锁而做的准备。

​ **explain.executionStats.executionStages.restoreState**

​ 查询阶段恢复保存的执行状态的次数，例如，在恢复之前已产生的锁之后。

​ **explain.executionStats.executionStages.isEOF**

​ 指定执行阶段是否已到达流的末尾：

​ 如果`true`或`1`，则执行阶段已到达流的末尾。

​ 如果`false`或`0`，则阶段可能仍会返回结果。例如，考虑一个具有限制的查询，其执行阶段由查询`LIMIT`的输入阶段组

​ 成`IXSCAN`。如果查询返回的值超过指定的限制，则该`LIMIT`阶段将报告，但其基础阶段将报告。**isEOF: 1IXSCANisEOF: 0**

​ **explain.executionStats.executionStages.inputStage.keysExamined**

​ 对于扫描索引的查询执行阶段（例如IXSCAN）， `keysExamined`是在索引扫描过程中检查的入站和出站键的总数。如果索引扫描 由单个连续范围的键组成，则仅需要检查入站键。如果索引范围由几个键范围组成，则索引扫描执行过程可能会检查越界键，以便 从一个范围的末尾跳到下一个范围的末尾。

考虑以下示例，其中有一个字段索引， `x`并且集合包含100个文档，其`x`值从1到100：

```
db.keys.find( { x : { $in : [ 3, 4, 50, 74, 75, 90 ] } } ).explain( "executionStats" )
```

​ 查询将扫描键**3**和**4**。然后它将扫描键**5**，检测它是否超出范围，并跳到下一个键**50**。

​ 继续这个过程，查询扫描键3、4、5、50、51、74、75、76、90和91。键5,51,76和91是仍在检查的超出范围的

​ 键。**keysExamined**的值为10。

​ **explain.executionStats.executionStages.inputStage.docsExamined**

​ 指定在查询执行阶段扫描的文档数量。

​ 用于**COLLSCAN**阶段，以及从集合检索文档的阶段(例如**FETCH**)

​ **explain.executionStats.executionStages.inputStage.seeks**

​ 版本3.4中的新特性:仅用于索引扫描\*\*(IXSCAN)\*\*阶段。

​ 为了完成索引扫描，我们必须将索引游标查找到新位置的次数。

**explain.executionStats.allPlansExecution**

​ 包含在计划选择阶段捕获的胜出计划和被否决计划的部分执行信息。只有当explain在所有计划执行冗长模式下运行时，该字段才 会出现。

### `serverInfo`

* 未分片集合
* 分片集合

对于未分片的集合，`explain`返回`serverInfo`MongoDB实例的以下 信息：

```
“ serverInfo”：{ 
   “ host”：<string>，
   “ port”：<int>，
   “ version”：<string>，
   “ gitVersion”：<string> 
}
```

对于分片集合，`explain`返回`serverInfo`每个访问的分片的，并返回的 顶级 `serverInfo`对象[`mongos`](https://docs.mongodb.com/manual/reference/program/mongos/#bin.mongos)。

```
"queryPlanner" : {
   ...
   "winningPlan" : {
      "stage" : <STAGE1>,
      "shards" : [
         {
            "shardName" : <string>,
            "connectionString" : <string>,
            "serverInfo" : {
               "host" : <string>,
               "port" : <int>,
               "version" : <string>,
               "gitVersion" : <string>
            },
            ...
         }
         ...
      ]
   }
},
"serverInfo" : {      // serverInfo for mongos
  "host" : <string>,
  "port" : <int>,
  "version" : <string>,
  "gitVersion" : <string>
}
```

## 3.0格式变更

从MongoDB 3.0开始，结果的格式和字段`explain` 与以前的版本已更改。以下列出了一些主要区别。

### 集合扫描与索引使用

如果查询计划者选择了集合扫描，则解释结果将包括一个`COLLSCAN`阶段。

如果查询计划者选择了索引，则说明结果包括一个 `IXSCAN`阶段。该阶段包括诸如索引键样式，遍历方向和索引边界之类的信息。

在以前的MongoDB版本中，`cursor.explain()`返回的 `cursor`字段值为：

* `BasicCursor` 用于收集扫描，
* `BtreeCursor <index name> [<direction>]` 用于索引扫描。

有关收集扫描和索引扫描的执行统计信息的更多信息，请参见[分析查询性能](https://docs.mongodb.com/manual/tutorial/analyze-query-plan/)。

### 覆盖查询

当索引涵盖查询时，MongoDB既可以匹配查询条件\*\*，也\*\*可以仅使用索引键返回结果；即MongoDB无需检查集合中的文档即可返回结果。

当索引覆盖查询时，解释结果的`IXSCAN` 阶段**不是**该阶段的后代`FETCH`，而在 [executionStats中](https://docs.mongodb.com/manual/reference/explain-results/#executionstats)，`totalDocsExamined`is是`0`。

在MongoDB的早期版本中，`cursor.explain()`返回该 `indexOnly`字段以指示索引是否覆盖查询。

### 索引交集

对于[索引交叉计划](https://docs.mongodb.com/manual/core/index-intersection/)，结果将包括一个`AND_SORTED`阶段或一个`AND_HASH` 包含[`inputStages`](https://docs.mongodb.com/manual/reference/explain-results/#explain.queryPlanner.winningPlan.inputStages)详细描述索引的数组的阶段。例如：

```
{ 
   “ stage”  ： “ AND_SORTED” ，
   “ inputStages”  ： [ 
      { 
         “ stage”  ： “ IXSCAN” ，
         ... 
      }，
      { 
         “ stage”  ： “ IXSCAN” ，
         ... 
      } 
   ] 
}
```

在以前的MongoDB版本中，`cursor.explain()`返回`cursor`值为index交集的 字段。`Complex Plan`

### `$or`表达式

如果MongoDB对[`$or`](https://docs.mongodb.com/manual/reference/operator/query/or/#op._S_or)表达式使用索引，则结果将包括`OR`带有`inputStages`详细索引的数组的阶段 ；例如：

复制复制的

```
{ 
   “ stage”  ： “ OR” ，
   “ inputStages”  ： [ 
      { 
         “ stage”  ： “ IXSCAN” ，
         ... 
      }，
      { 
         “ stage”  ： “ IXSCAN” ，
         ... 
      }，
      ... 
   ] 
}
```

在MongoDB的早期版本中，`cursor.explain()`返回`clauses`详细说明索引的 数组。

#### 分类阶段

如果MongoDB可以使用索引扫描来获取请求的排序顺序，则结果将**不**包含`SORT`阶段。否则，如果MongoDB无法使用索引进行排序，则`explain`结果将包括一个 `SORT`阶段。

在MongoDB 3.0之前，`cursor.explain()`返回此 `scanAndOrder`字段以指定MongoDB是否可以使用索引顺序返回排序的结果。

译者：杨帅

校对：杨帅


# 分析查询表现

**在本页面**

* [评估查询的性能](#评估)

该 [`cursor.explain("executionStats")`](https://docs.mongodb.com/manual/reference/method/cursor.explain/#cursor.explain) 和[`db.collection.explain("executionStats")`](https://docs.mongodb.com/manual/reference/method/db.collection.explain/#db.collection.explain)方法提供了有关查询的性能统计信息。这些统计信息可用于衡量查询是否以及如何使用索引。

[`db.collection.explain()`](https://docs.mongodb.com/manual/reference/method/db.collection.explain/#db.collection.explain) 提供关于其他操作(如[`db.collection.update()`](https://docs.mongodb.com/manual/reference/method/db.collection.update/#db.collection.update))执行的信息。详细信息请参见[`db.collection.explain()`](https://docs.mongodb.com/manual/reference/method/db.collection.explain/#db.collection.explain)

## 评估查询的性能

考虑一个包含以下文件的收集清单:

```
{ "_id" : 1, "item" : "f1", type: "food", quantity: 500 }
{ "_id" : 2, "item" : "f2", type: "food", quantity: 100 }
{ "_id" : 3, "item" : "p1", type: "paper", quantity: 200 }
{ "_id" : 4, "item" : "p2", type: "paper", quantity: 150 }
{ "_id" : 5, "item" : "f3", type: "food", quantity: 300 }
{ "_id" : 6, "item" : "t1", type: "toys", quantity: 500 }
{ "_id" : 7, "item" : "a1", type: "apparel", quantity: 250 }
{ "_id" : 8, "item" : "a2", type: "apparel", quantity: 400 }
{ "_id" : 9, "item" : "t2", type: "toys", quantity: 50 }
{ "_id" : 10, "item" : "f4", type: "food", quantity: 75 }
```

### 没有索引的查询

以下查询检索的文档中，**quantity**字段的值在**100**到**200**之间，包括:

```
db.inventory.find( { quantity: { $gte: 100, $lte: 200 } } )
```

查询返回以下文档:

```
{ "_id" : 2, "item" : "f2", "type" : "food", "quantity" : 100 }
{ "_id" : 3, "item" : "p1", "type" : "paper", "quantity" : 200 }
{ "_id" : 4, "item" : "p2", "type" : "paper", "quantity" : 150 }
```

要查看所选的查询计划，请将[`cursor.explain("executionStats")`](https://docs.mongodb.com/manual/reference/method/cursor.explain/#cursor.explain)游标方法链接到**find**命令的末尾:

```
db.inventory.find(
   { quantity: { $gte: 100, $lte: 200 } }
).explain("executionStats")
```

[`explain()`](https://docs.mongodb.com/manual/reference/method/cursor.explain/#cursor.explain) 返回以下结果：

```
{
   "queryPlanner" : {
         "plannerVersion" : 1,
         ...
         "winningPlan" : {
            "stage" : "COLLSCAN",
            ...
         }
   },
   "executionStats" : {
      "executionSuccess" : true,
      "nReturned" : 3,
      "executionTimeMillis" : 0,
      "totalKeysExamined" : 0,
      "totalDocsExamined" : 10,
      "executionStages" : {
         "stage" : "COLLSCAN",
         ...
      },
      ...
   },
   ...
}
```

* [`queryPlanner.winningPlan.stage`](https://docs.mongodb.com/manual/reference/explain-results/#explain.queryPlanner.winningPlan.stage)显示 `COLLSCAN`以指示收集扫描。

  收集扫描表明， [`mongod`](https://docs.mongodb.com/manual/reference/program/mongod/#bin.mongod)必须逐个文档扫描整个收集文档以识别结果。这通常是昂贵的操作，并且可能导致查询缓慢。
* [`executionStats.nReturned`](https://docs.mongodb.com/manual/reference/explain-results/#explain.executionStats.nReturned)显示`3`表示查询匹配并返回三个文档。
* [`executionStats.totalKeysExamined`](https://docs.mongodb.com/manual/reference/explain-results/#explain.executionStats.totalKeysExamined)显示`0` 以指示这是查询未使用索引。
* [`executionStats.totalDocsExamined`](https://docs.mongodb.com/manual/reference/explain-results/#explain.executionStats.totalDocsExamined)屏幕显示`10` MongoDB必须扫描十个文档（即集合中的所有文档）才能找到三个匹配的文档。

匹配文档的数量和检查文档的数量之间的差异可能表明，为了提高效率，查询可能会受益于索引的使用。

### 查询与索引

为了支持对**quantity**字段的查询，请在**quantity**字段上添加索引:

```
db.inventory.createIndex( { quantity: 1 } )
```

要查看查询计划统计信息，请使用\*\*explain(“executionStats”)\*\*方法:

```
db.inventory.find(
   { quantity: { $gte: 100, $lte: 200 } }
).explain("executionStats")
```

该[explain()](https://docs.mongodb.com/manual/reference/method/cursor.explain/#cursor.explain)方法返回以下结果:

```
{
   "queryPlanner" : {
         "plannerVersion" : 1,
         ...
         "winningPlan" : {
               "stage" : "FETCH",
               "inputStage" : {
                  "stage" : "IXSCAN",
                  "keyPattern" : {
                     "quantity" : 1
                  },
                  ...
               }
         },
         "rejectedPlans" : [ ]
   },
   "executionStats" : {
         "executionSuccess" : true,
         "nReturned" : 3,
         "executionTimeMillis" : 0,
         "totalKeysExamined" : 3,
         "totalDocsExamined" : 3,
         "executionStages" : {
            ...
         },
         ...
   },
   ...
}
```

* [`queryPlanner.winningPlan.inputStage.stage`](https://docs.mongodb.com/manual/reference/explain-results/#explain.queryPlanner.winningPlan.inputStage)显示 `IXSCAN`以指示索引的使用。
* [`executionStats.nReturned`](https://docs.mongodb.com/manual/reference/explain-results/#explain.executionStats.nReturned) 显示`3`表示查询匹配并返回三个文档。
* [`executionStats.totalKeysExamined`](https://docs.mongodb.com/manual/reference/explain-results/#explain.executionStats.totalKeysExamined)显示`3` 以指示MongoDB扫描了三个索引条目。检查的键数与返回的文档数匹配，这意味着[`mongod`](https://docs.mongodb.com/manual/reference/program/mongod/#bin.mongod)只需检查索引键即可返回结果。在 [`mongod`](https://docs.mongodb.com/manual/reference/program/mongod/#bin.mongod)没有扫描所有的文件，只有三个匹配文档不得不被拉入内存中。这导致非常有效的查询。
* [`executionStats.totalDocsExamined`](https://docs.mongodb.com/manual/reference/explain-results/#explain.executionStats.totalDocsExamined)屏幕显示`3` MongoDB扫描了三个文档。

如果没有索引，查询将扫描包含**10**个文档的整个集合，以返回**3**个匹配的文档。查询还必须扫描每个文档的全部内容，可能会将它们拉到内存中。这将导致昂贵的查询操作，并且可能会很慢。

当使用索引运行时，查询扫描了**3**个索引项和**3**个文档，以返回**3**个匹配的文档，从而产生一个非常高效的查询。

### 比较索引的性能

要手动比较使用多个索引的查询的性能，可以将 [`hint()`](https://docs.mongodb.com/manual/reference/method/cursor.hint/#cursor.hint)方法与[`explain()`](https://docs.mongodb.com/manual/reference/method/cursor.explain/#cursor.explain)方法结合使用。

考虑以下查询:

```
db.inventory.find( {
   quantity: {
      $gte: 100, $lte: 300
   },
   type: "food"
} )
```

查询返回以下文档:

```
{ "_id" : 2, "item" : "f2", "type" : "food", "quantity" : 100 }
{ "_id" : 5, "item" : "f3", "type" : "food", "quantity" : 300 }
```

要支持查询，添加[复合索引](https://docs.mongodb.com/manual/core/index-compound/)。对于[复合索引](https://docs.mongodb.com/manual/core/index-compound/)，字段的顺序很重要。

例如，添加以下两个复合索引。第一个索引首先按数量字段排序，然后按类型字段排序。第二个索引首先按类型排序，然后是**quantity**字段。

```
db.inventory.createIndex( { quantity: 1, type: 1 } )
db.inventory.createIndex( { type: 1, quantity: 1 } )
```

评估第一个索引对查询的影响:

```
db.inventory.find(
   { quantity: { $gte: 100, $lte: 300 }, type: "food" }
).hint({ quantity: 1, type: 1 }).explain("executionStats")
```

[`explain()`](https://docs.mongodb.com/manual/reference/method/cursor.explain/#cursor.explain)方法返回如下输出:

```
{
   "queryPlanner" : {
      ...
      "winningPlan" : {
         "stage" : "FETCH",
         "inputStage" : {
            "stage" : "IXSCAN",
            "keyPattern" : {
               "quantity" : 1,
               "type" : 1
            },
            ...
            }
         }
      },
      "rejectedPlans" : [ ]
   },
   "executionStats" : {
      "executionSuccess" : true,
      "nReturned" : 2,
      "executionTimeMillis" : 0,
      "totalKeysExamined" : 5,
      "totalDocsExamined" : 2,
      "executionStages" : {
      ...
      }
   },
   ...
}
```

MongoDB扫描了5个索引键([`executionStats.totalKeysExamined`](https://docs.mongodb.com/manual/reference/explain-results/#explain.executionStats.totalKeysExamined))以返回2个匹配的文档([`executionStats.nReturned`](https://docs.mongodb.com/manual/reference/explain-results/#explain.executionStats.nReturned))。

评估第二个索引对查询的影响:

```
db.inventory.find(
   { quantity: { $gte: 100, $lte: 300 }, type: "food" }
).hint({ type: 1, quantity: 1 }).explain("executionStats")
```

[`explain()`](https://docs.mongodb.com/manual/reference/method/cursor.explain/#cursor.explain)方法返回如下输出:

```
{
   "queryPlanner" : {
      ...
      "winningPlan" : {
         "stage" : "FETCH",
         "inputStage" : {
            "stage" : "IXSCAN",
            "keyPattern" : {
               "type" : 1,
               "quantity" : 1
            },
            ...
         }
      },
      "rejectedPlans" : [ ]
   },
   "executionStats" : {
      "executionSuccess" : true,
      "nReturned" : 2,
      "executionTimeMillis" : 0,
      "totalKeysExamined" : 2,
      "totalDocsExamined" : 2,
      "executionStages" : {
         ...
      }
   },
   ...
}
```

MongoDB扫描了2个索引键([`executionStats.totalKeysExamined`](https://docs.mongodb.com/manual/reference/explain-results/#explain.executionStats.totalKeysExamined))以返回2个匹配的文档([`executionStats.nReturned`](https://docs.mongodb.com/manual/reference/explain-results/#explain.executionStats.nReturned))。

对于这个示例查询，复合索引\*\*{type: 1, quantity: 1}**比复合索引**{quantity: 1, type: 1}\*\*更有效。

​ 也可以看看

​ [查询优化](https://docs.mongodb.com/manual/core/query-optimization/)，[查询计划](https://docs.mongodb.com/manual/core/query-plans/)， [优化查询性能](https://docs.mongodb.com/manual/tutorial/optimize-query-performance-with-indexes-and-projections/)， [索引策略](https://docs.mongodb.com/manual/applications/indexes/)

译者：杨帅

校对：杨帅


# Tailable 游标

默认情况下，当客户端使用完游标中的所有结果时，MongoDB将自动关闭游标。但是，对于有上限的集合，您可以使用一个可定制的游标，该游标在客户端穷尽初始游标的结果后保持打开状态。可跟踪游标在概念上等同于带-f选项的tail Unix命令(即“follow”模式)。在客户端向有上限的集合中插入新的额外文档之后，可定制游标将继续检索文档。

在具有高写量的有上限集合上使用可定制游标，因为索引不实用。例如，MongoDB复制使用可跟踪的游标跟踪主服务器的[oplog](https://docs.mongodb.com/manual/reference/glossary/#term-oplog).

> **\[success] 注意**
>
> 如果查询位于索引字段上，则不要使用可跟踪游标，而是使用常规游标。跟踪查询返回的索引字段的最后一个值。要检索新添加的文档，使用查询条件中索引字段的最后一个值再次查询集合，如下面的示例所示:
>
> ```
> db.<collection>.find( { indexedField: { $gt: <lastvalue> } } )
> ```

考虑以下与可跟踪游标相关的行为:

* 可跟踪游标不使用索引，并按自然顺序返回文档。
* 由于可tailable游标不使用索引，因此查询的初始扫描可能开销较大;但是，在最初耗尽游标之后，后续对新添加文档的检索就不那么昂贵了。
* 可跟踪游标可能会死亡或无效，如果有下列情况:

  * 查询返回不匹配。
  * 游标返回集合“末尾”的文档，然后应用程序删除该文档。

  一个已死亡游标的id为0。

请参阅[驱动程序文档](https://docs.mongodb.com/ecosystem/drivers)，以获取特定于驱动程序的方法以指定可跟踪游标。

译者：杨帅

校对：杨帅


# MongoDB聚合

在本页面

* [聚合管道](#aggregation-pipeline)
* [Map-Reduce](#map-reduce)
* [单用途聚合操作](#single-purpose-aggregation-operations)
* [附加功能和行为](#additional-features-and-behaviors)

聚合操作处理数据记录和 return 计算结果。聚合操作将来自多个文档的值组合在一起，并且可以对分组数据执行各种操作以返回单个结果。 MongoDB 提供了三种执行聚合的方法：[聚合管道](#聚合管道)，[map-reduce function](#map-reduce)和[单一目的聚合方法](#单用途聚合操作)。

## 聚合管道

MongoDB 的[Aggregation framework](/aggregation/aggregation-pipeline)是以数据处理管道的概念为蓝本的。文档进入多阶段管道，将文档转换为聚合结果。例如：

在这个例子中：

```
db.orders.aggregate([
   { $match: { status: "A" } },
   { $group: { _id: "$cust_id", total: { $sum: "$amount" } } }
])
```

**第一阶段**：[`$match`](/aggregation)阶段按`status`字段过滤文档，并将`status`等于`"A"`的文档传递到下一阶段。

**第二阶段**：[`$group`](/aggregation)阶段按`cust_id`字段将文档分组，以计算每个唯一值`cust_id`的金额总和。

最基本的管道阶段提供\_过滤器\_，其操作类似于查询和修改输出文档格式的\_文档转换\_。

其他管道操作提供了用于按特定字段对文档进行分组和排序的工具，以及用于汇总包括文档数组在内的数组内容的工具。另外，管道阶段可以将[运算符](/aggregation)用于诸如计算平均值或连接字符串之类的任务。

管道使用MongoDB中的原生操作提供有效的数据聚合，并且是MongoDB中数据聚合的首选方法。

聚合管道可以在[分片集合 sharded collection](/aggregation)上运行。

聚合管道可以使用索引来改善其某些阶段的性能。此外，聚合管道具有内部优化阶段。有关详细信息，请参阅[管道操作和索引](/aggregation/aggregation-pipeline)和[聚合管道优化](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)。

## Map-Reduce

MongoDB 还提供[map-reduce](/aggregation/map-reduce)操作来执行聚合。通常，map-reduce 操作有两个阶段：一个 map 阶段，它处理每个文档并为每个输入文档发出一个或多个对象，以及将map操作的输出组合在一起的\_reduce\_阶段。可选地，map-reduce 可以具有最终化阶段以对结果进行最终修改。与其他聚合操作一样，map-reduce 可以指定查询条件以选择输入文档以及对结果排序和限制。

Map-reduce 使用自定义 JavaScript 函数来执行 map 和 reduce操作，以及可选的 finalize 操作。与聚合管道相比，自定义JavaScript提供了很大的灵活性，但通常情况下，map-reduce比聚合管道效率低，而且更复杂。

Map-reduce 可以在[分片集合 sharded collection](/aggregation)上运行。 Map-reduce 操作也可以输出到分片集合。有关详细信息，请参阅[聚合管道和分片集合](/aggregation/aggregation-pipeline/aggregation-pipeline-and-sharded-collections)和[Map-Reduce 和 Sharded Collections](/aggregation/map-reduce/map-reduce-and-sharded-collections)。

> **\[success] 注意**
>
> 从 MongoDB 2.4 开始，在 map-reduce 操作中无法访问某些mongoshell 函数和属性。 MongoDB 2.4 还支持多个 JavaScript 操作以在同一时间运行。在 MongoDB 2.4 之前，JavaScript code 在单个线程中执行，引发了 map-reduce 的并发问题。

![带注释的 map-reduce 操作图](/files/ePqSMXhRfjxuV9zNwXcB)

## 单用途聚合操作

MongoDB 还提供 [db.collection.estimatedDocumentCount()](/aggregation), [db.collection.count()](/can-kao/mongo-shell-methods/collection-methods/db-collection-count)和[db.collection.distinct()](/can-kao/mongo-shell-methods/collection-methods/db-collection-distinct)。

所有这些操作都聚合来自单个集合的文档。虽然这些操作提供了对常见聚合过程的简单访问，但它们缺乏聚合管道和 map-reduce 的灵活性和功能。

![带注释的不同操作的图表](/files/ibMPwR0yyKvV9OLHAuyV)

## 附加功能和行为

有关聚合管道 map-reduce 和特殊组功能的特性比较，请参阅[聚合命令比较](/aggregation/aggregation-reference/aggregation-commands-commparison)。

译者：李冠飞

### MongoDB中文社区

![MongoDB中文社区—MongoDB爱好者技术交流平台](https://mongoing.com/wp-content/uploads/2020/09/6de8a4680ef684d-2.png)

| 资源列表推荐             | 资源入口                                                                                                                                                                                                                                                                       |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| MongoDB中文社区官网      | <https://mongoing.com/>                                                                                                                                                                                                                                                    |
| 微信服务号 ——最新资讯和优质文章  | Mongoing中文社区（mongoing-mongoing）                                                                                                                                                                                                                                            |
| 微信订阅号 ——发布文档翻译内容   | MongoDB中文用户组（mongoing123）                                                                                                                                                                                                                                                  |
| 官方微信号 —— 官方最新资讯    | MongoDB数据库（MongoDB-China）                                                                                                                                                                                                                                                  |
| MongoDB中文社区组委会成员介绍 | <https://mongoing.com/core-team-members>                                                                                                                                                                                                                                   |
| MongoDB中文社区翻译小组介绍  | <https://mongoing.com/translators>                                                                                                                                                                                                                                         |
| MongoDB中文社区微信技术交流群 | 添加社区助理小芒果微信（ID:mongoingcom），并备注 mongo                                                                                                                                                                                                                                      |
| MongoDB中文社区会议及文档资源 | <https://mongoing.com/resources>                                                                                                                                                                                                                                           |
| MongoDB中文社区大咖博客    | [基础知识](https://mongoing.com/basic-knowledge) [性能优化](https://mongoing.com/performance-optimization) [原理解读](https://mongoing.com/interpretation-of-principles) [运维监控](https://mongoing.com/operation-and-maintenance-monitoring) [最佳实践](https://mongoing.com/best-practices) |
| MongoDB白皮书         | <https://mongoing.com/mongodb-download-white-paper>                                                                                                                                                                                                                        |
| MongoDB初学者教程-7天入门  | <https://mongoing.com/mongodb-beginner-tutorial>                                                                                                                                                                                                                           |
| 社区活动邮件订阅           | <https://sourl.cn/spszjN>                                                                                                                                                                                                                                                  |


# 聚合管道

在本页面

* [管道](#pipeline)
* [管道表达式](#pipeline-expressions)
* [聚合管道行为](#aggregation-pipeline-behavior)
* [注意事项](#considerations)

聚合管道是用于数据聚合的框架，其模型基于数据处理管道的概念。文档进入多阶段管道，将文档转换为聚合结果。例如：

在这个例子中

```
db.orders.aggregate([
    { $match: { status: "A" } },
    { $group: { _id: "$cust_id", total: { $sum: "$amount" } } }
])
```

**第一阶段**：[`$match`](/aggregation/aggregation-pipeline)阶段按`status`字段过滤文档，并将`status`等于`"A"`的文档传递到下一阶段。

**第二阶段**：[`$group`](/aggregation/aggregation-pipeline)阶段按`cust_id`字段将文档分组，以计算每个`cust_id`唯一值的金额总和。

## 管道

MongoDB 聚合管道由多个[阶段](/can-kao/yun-suan-fu/aggregation-pipeline-stages)组成。每个阶段在文档通过管道时转换文档。管道阶段不需要为每个输入文档生成一个输出文档; 如：某些阶段可能会生成新文档或过滤掉文档。

Pipeline阶段可以与外管道出现多次[`$out`](/aggregation/aggregation-pipeline)，[`$merge`](/aggregation/aggregation-pipeline)和 [`$geoNear`](/aggregation/aggregation-pipeline)阶段。有关所有可用阶段的列表，请参见 [聚合管道阶段](/aggregation/aggregation-pipeline)。

MongoDB 在[mongo](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/docs/Reference/MongoDB-Package-Components/mongo.md) shell 中提供[db.collection.aggregate()](/can-kao/mongo-shell-methods/collection-methods/db-collection-aggregate)方法，在聚合管道中提供[聚合](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/docs/Reference/Database-Commands/Aggregation-Commands.md)命令。

对于聚合管道的 example 用法，请考虑[使用用户首选项数据进行聚合](/aggregation/aggregation-pipeline/example-with-user-preference-data)和[使用 Zip Code 数据集进行聚合](/aggregation/aggregation-pipeline/example-with-zip-code-data)。

从MongoDB 4.2开始，您可以使用聚合管道在以下位置进行更新：

| 命令                                                   | Mongoshall方法                                                                                                                                                                                                                                                                                                                                                          |
| ---------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`findAndModify`](/aggregation/aggregation-pipeline) | [db.collection.findOneAndUpdate（）](/aggregation/aggregation-pipeline) [db.collection.findAndModify（）](/aggregation/aggregation-pipeline)                                                                                                                                                                                                                              |
| [`pdate`](/aggregation/aggregation-pipeline)         | [db.collection.updateOne（）](/aggregation/aggregation-pipeline) [db.collection.updateMany（）](/aggregation/aggregation-pipeline) [db.collection.update（）](/aggregation/aggregation-pipeline) [Bulk.find.update（）](/aggregation/aggregation-pipeline) [Bulk.find.updateOne（）](/aggregation/aggregation-pipeline) [Bulk.find.upsert（）](/aggregation/aggregation-pipeline) |

> **\[success] 也可以看看**
>
> [聚合管道更新](/aggregation/aggregation-pipeline)

## 管道表达式

某些管道阶段将管道表达式作为操作数。管道表达式指定要应用于输入文档的转换。表达式具有[文档](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Introduction-to-MongoDB/Documents.md)结构，可以包含其他[表达式](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)。

管道表达式只能对管道中的当前文档进行操作，并且不能引用其他文档中的数据：表达式操作提供文档的内存转换。

通常，表达式是无状态的，只有在聚合过程看到表达式时才计算，只有一个例外：[累加器](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)表达式。

在[$group](/aggregation/aggregation-pipeline)阶段中使用的累加器在记录管道中的进程时维护它们的状态(如： 总计，最大值，最小值和相关数据)。

Mongodb 3.2的变化：[$project](/aggregation/aggregation-pipeline)阶段有一些累加器可用;但是，在[$project](/aggregation/aggregation-pipeline)阶段使用时，累加器不会跨文档维护它们的状态。

有关表达式的更多信息，请参阅[表达式](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)。

## 聚合管道行为

在 MongoDB 中，[管道](/aggregation/aggregation-pipeline)命令在单个集合上运行，从逻辑上将整个集合传递到聚合管道。为了尽可能优化操作，请使用以下策略以避免扫描整个集合。

### 管道运算符和索引

MongoDB的[query planner](/aggregation/aggregation-pipeline)分析聚合管道，以确定是否可以使用[索引](https://docs.mongodb.com/manual/indexes/#indexes)来改善管道性能。例如，以下管道阶段可以利用索引：

> **\[success] 注意**
>
> 以下管道阶段并不代表可以使用索引的所有阶段的完整列表。

* **$match**

  如果[`$match`](/aggregation/aggregation-pipeline)阶段出现在管道的开始，该阶段可以使用索引来过滤文档。
* **$sort**

  只要前面没有[`$project`](/aggregation/aggregation-pipeline)，[`$unwind`](/aggregation/aggregation-pipeline)或 [`$group`](/aggregation/aggregation-pipeline)阶段，[`$sort`](/aggregation/aggregation-pipeline)阶段可以使用索引。
* **$group**

  如果满足下列所有的条件，[`$group`](/aggregation/aggregation-pipeline)阶段有时可以使用的索引来查找每一个组中的第一文档：

  * [`$group`](/aggregation/aggregation-pipeline)阶段之前是一个[`$sort`](/aggregation/aggregation-pipeline) 阶段，该阶段对字段进行分组
  * 在分组的字段上有一个索引，它与排序顺序匹配
  * [`$group`](/aggregation/aggregation-pipeline)阶段中使用的唯一累加器是 [`$first`](/aggregation/aggregation-pipeline)

  有关示例，请参见[优化以返回每个组的第一个文档](/aggregation/aggregation-pipeline)。
* **$geoNear**

  [`$geoNear`](/aggregation/aggregation-pipeline)管道运算符利用地理空间索引。在使用时[`$geoNear`](/aggregation/aggregation-pipeline)， [`$geoNear`](/aggregation/aggregation-pipeline)管道操作必须出现在聚合管道的第一阶段出现。

> Mongodb 3.2 版本的改变：从MongoDB 3.2开始，索引可以覆盖聚合管道。在MongoDB 2.6和3.0中，索引无法覆盖聚合管道，因为即使管道使用索引，聚合仍需要访问实际文档。

### 早期过滤

如果聚合操作仅需要集合中的数据子集，请使用[$match](/aggregation/aggregation-pipeline)，[$limit](/aggregation/aggregation-pipeline)和[$skip](/aggregation/aggregation-pipeline)阶段来限制在管道开头输入的文档。当放置在管道的开头时，[$match](/aggregation/aggregation-pipeline)操作使用合适的索引来仅扫描集合中的匹配文档。

在管道的开头放置[$match](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/reference-operator-aggregation-match.html#pipe._S_match)管道阶段后跟[$sort](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/reference-operator-aggregation-sort.html#pipe._S_sort)阶段在逻辑上等同于具有排序的单个查询并且可以使用索引。如果可能，将[$match](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/reference-operator-aggregation-match.html#pipe._S_match) 操作符放在管道的开头。

### 附加功能

聚合管道具有内部优化阶段，为 operators 的某些序列提供改进的 performance。有关详细信息，请参阅[聚合管道优化](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)。

聚合管道支持对分片集合的操作。见[聚合管道和分片集合](/aggregation/aggregation-pipeline/aggregation-pipeline-and-sharded-collections)。

* [聚合管道优化](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)
* [聚合管道限制](/aggregation/aggregation-pipeline/aggregation-pipeline-limits)
* [聚合管道和分片集合](/aggregation/aggregation-pipeline/aggregation-pipeline-and-sharded-collections)
* [使用 Zip Code 数据集进行聚合](/aggregation/aggregation-pipeline/example-with-zip-code-data)
* [Example with User Preference Data](/aggregation/aggregation-pipeline/example-with-user-preference-data)

## 注意事项

### 分片集合

聚合管道支持对分片集合的操作。请参阅[聚合管道和分片集合](/aggregation/aggregation-pipeline/aggregation-pipeline-and-sharded-collections)。

### 聚合管道与Map-Reduce的比较

聚合管道为[map-reduce](/aggregation/aggregation-pipeline)提供了一种替代方案，并且对于map-reduce的复杂性可能没有保障的聚合任务，它可能是首选的解决方案。

### 限制

聚合管道对值类型和结果大小有一些限制。有关聚合管道的限制和限制的详细信息，请参见[聚合管道限制](/aggregation/aggregation-pipeline/aggregation-pipeline-limits)。

### 管道优化

管道优化聚合管道具有内部优化阶段，可为某些操作符序列提供改进的性能。有关详细信息，请参阅[聚合管道优化](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)。

译者：李冠飞 刘翔

校对：李冠飞


# 聚合管道优化

在本页面

* [投影优化](#projection-optimization)
* [管道序列优化](#pipeline-sequence-optimization)
* [管道聚结优化](#pipeline-coalescence-optimization)
* [例子](#example)

聚合管道操作具有优化阶段，该阶段试图重塑管道以改善性能。

要查看优化程序如何转换特定聚合管道，请在[db.collection.aggregate()](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)方法中包含[explain](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)选项。

优化可能会在不同版本之间发生变化。

## 投影优化

聚合管道可以确定它是否仅需要文档中的字段的子集来获得结果。如果是这样，管道将只使用那些必需的字段，减少通过管道的数据量。

## 管道序列优化

### ($project or $unset or $addFields or $set) + $match 序列优化

对于包含投影阶段([$project](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)或[$unset](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)或[$addFields](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)或[$set](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization))后跟[$match](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段的聚合管道，MongoDB 将[$match](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段中不需要在投影阶段计算的值的任何过滤器移动到投影前的新[$match](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段。

如果聚合管道包含多个投影 and/or [$match](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段，MongoDB 会为每个[$match](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段执行此优化，将每个[$match](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)过滤器移动到过滤器不依赖的所有投影阶段之前。

考虑以下阶段的管道：

```
{ $addFields: {
    maxTime: { $max: "$times" },
    minTime: { $min: "$times" }
} },
{ $project: {
    _id: 1, name: 1, times: 1, maxTime: 1, minTime: 1,
    avgTime: { $avg: ["$maxTime", "$minTime"] }
} },
{ $match: {
    name: "Joe Schmoe",
    maxTime: { $lt: 20 },
    minTime: { $gt: 5 },
    avgTime: { $gt: 7 }
} }
```

优化器将[$match](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段分成四个单独的过滤器，一个用于[$match](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)查询文档中的每个键。然后优化器将每个筛选器移动到尽可能多的投影阶段之前，根据需要创建新的[$match](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段。鉴于此示例，优化程序生成以下优化管道：

```
{ $match: { name: "Joe Schmoe" } },
{ $addFields: {
                maxTime: { $max: "$times" },
        minTime: { $min: "$times" }
} },
{ $match: { maxTime: { $lt: 20 }, minTime: { $gt: 5 } } },
{ $project: {
        _id: 1, name: 1, times: 1, maxTime: 1, minTime: 1,
        avgTime: { $avg: ["$maxTime", "$minTime"] }
} },
{ $match: { avgTime: { $gt: 7 } } }
```

[$match](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)过滤器`{ avgTime: { $gt: 7 } }`取决于[$project](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段来计算`avgTime`字段。 [$project](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段是此管道中的最后一个投影阶段，因此`avgTime`上的[$match](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)过滤器无法移动。

`maxTime`和`minTime`字段在[$addFields](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段计算，但不依赖于[$project](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段。优化器为这些字段上的过滤器创建了一个新的[$match](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-match.html#pipe._S_match)阶段，并将其放在[$project](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段之前。

[$match](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)过滤器`{ name: "Joe Schmoe" }`不使用在[$project](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)或[$addFields](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段计算的任何值，因此它在两个投影阶段之前被移动到新的[$match](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段。

> **\[success] 注意**
>
> 优化后，过滤器`{ name: "Joe Schmoe" }`位于管道开头的[$match](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段。这具有额外的好处，即允许聚合在最初查询集合时在`name`字段上使用索引。有关更多信息，请参见[管道操作符和索引](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)。

### $sort + $match 序列优化

如果序列中带有[$sort](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)后跟[$match](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)，则[$match](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)会移动到[$sort](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)之前，以最大程度的减少要排序的对象的数量。例如，如果管道包含以下阶段：

```
{ $sort: { age : -1 } }, 
{ $match: { status: 'A' } }
```

在优化阶段，优化程序将序列转换为以下内容：

```
{ $match: { status: 'A' } }, 
{ $sort: { age : -1 } }
```

### $redact + $match 序列优化

如果可能，当管道的[$redact](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段紧在[$match](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段之后时，聚合有时可以在[$redact](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段之前添加[$match](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段的一部分。如果添加的[$match](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段位于管道的开头，则聚合可以使用索引以及查询集合来限制进入管道的文档数。有关更多信息，请参见[管道操作符和索引](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)。 例如，如果管道包含以下阶段：

```
{ $redact: { $cond: { if: { $eq: [ "$level", 5 ] }, then: "$$PRUNE", else: "$$DESCEND" } } },
{ $match: { year: 2014, category: { $ne: "Z" } } }
```

优化器可以在[$redact](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段之前添加相同的[$match](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段：

```
{ $match: { year: 2014 } },
{ $redact: { $cond: { if: { $eq: [ "$level", 5 ] }, then: "$$PRUNE", else: "$$DESCEND" } } },
{ $match: { year: 2014, category: { $ne: "Z" } } }
```

### `$project`/ `$unset` + `$skip`序列优化

*3.2版本中的新功能。*

当有一个[`$project`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)或[`$unset`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)之后跟有[`$skip`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)序列时，[`$skip`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization) 会移至[`$project`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)之前。例如，如果管道包括以下阶段：

```
{ $sort: { age : -1 } },
{ $project: { status: 1, name: 1 } },
{ $skip: 5 }
```

在优化阶段，优化器将序列转换为以下内容：

```
{ $sort: { age : -1 } },
{ $skip: 5 },
{ $project: { status: 1, name: 1 } }
```

## 管道聚合优化

如果可能，优化阶段将一个管道阶段合并到其前身。通常，合并发生在任何序列重新排序优化之后。

### `$sort` + `$limit`合并

*Mongodb 4.0版本的改变。*

当一个[`$sort`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)先于[`$limit`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)，优化器可以聚结[`$limit`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)到[`$sort`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)，如果没有中间阶段的修改文件（例如，使用数[`$unwind`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)，[`$group`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)）。如果有管道阶段会更改和阶段之间的文档数，则MongoDB将不会合并[`$limit`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)到 。[`$sort`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)[`$sort`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)[`$limit`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)

例如，如果管道包括以下阶段：

```
{ $sort : { age : -1 } },
{ $project : { age : 1, status : 1, name : 1 } },
{ $limit: 5 }
```

在优化阶段，优化器将序列合并为以下内容：

```
{
    "$sort" : {
       "sortKey" : {
          "age" : -1
       },
       "limit" : NumberLong(5)
    }
},
{ "$project" : {
         "age" : 1,
         "status" : 1,
         "name" : 1
  }
}
```

这样，排序操作就可以仅在执行过程中保持最高`n`结果，这`n`是指定的限制，MongoDB仅需要将`n`项目存储在内存中 [\[1\]](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)。有关更多信息，请参见[$ sort运算符和内存](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)。

> 用`$skip`进行序列优化
>
> 如果[`$skip`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)在[`$sort`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization) 和[`$limit`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段之间有一个阶段，MongoDB将合并 [`$limit`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)到该[`$sort`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段并增加该 [`$limit`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)值[`$skip`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)。有关示例，请参见 [$ sort + $ skip + $ limit序列](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)。
>
> [\[1\]](https://docs.mongodb.com/manual/core/aggregation-pipeline-optimization/#id1)当优化仍将适用 `allowDiskUse`是`true`与`n`项目超过 [聚集内存限制](https://docs.mongodb.com/manual/core/aggregation-pipeline-limits/#agg-memory-restrictions)。

### `$limit`+ `$limit`合并

当[`$limit`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)紧接着另一个时 [`$limit`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)，两个阶段可以合并为一个阶段 [`$limit`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)，其中限制量为两个初始限制量中的较小者。例如，管道包含以下序列：

```
{ $limit: 100 },
{ $limit: 10 }
```

然后，第二[`$limit`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)级可以聚结到第一 [`$limit`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段，并导致在单个[`$limit`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization) 阶段，即限制量`10`是两个初始极限的最小`100`和`10`。

```
{ $limit: 10 }
```

### `$skip`+ `$skip`合并

当[`$skip`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)紧跟另一个[`$skip`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)，这两个阶段可合并成一个单一的[`$skip`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)，其中跳过量为总和的两个初始跳过量。例如，管道包含以下序列：

```
{ $skip: 5 },
{ $skip: 2 }
```

然后，第二[`$skip`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段可以合并到第一 [`$skip`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段，并导致单个[`$skip`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization) 阶段，其中跳过量`7`是两个初始限制`5`和的总和`2`。

```
{ $skip: 7 }
```

### `$match`+ `$match`合并

当一个[`$match`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)紧随另一个紧随其后时 [`$match`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)，这两个阶段可以合并为一个单独 [`$match`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)的条件 [`$and`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)。例如，管道包含以下序列：

```
{ $match: { year: 2014 } },
{ $match: { status: "A" } }
```

然后，第二[`$match`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段可以合并到第一 [`$match`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段，从而形成一个[`$match`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization) 阶段

```
{ $match: { $and: [ { "year" : 2014 }, { "status" : "A" } ] } }
```

### `$lookup` + `$unwind` 合并

*3.2版中的新功能。*

当a [`$unwind`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)立即紧随其后 [`$lookup`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)，并且在 领域[`$unwind`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)运行时，优化程序可以将其合并 到阶段中。这样可以避免创建较大的中间文档。`as`[`$lookup`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)[`$unwind`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)[`$lookup`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)

例如，管道包含以下序列：

```
{
  $lookup: {
    from: "otherCollection",
    as: "resultingArray",
    localField: "x",
    foreignField: "y"
  }
},
{ $unwind: "$resultingArray"}
```

优化器可以将[`$unwind`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段合并为 [`$lookup`](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段。如果使用`explain` 选项运行聚合，则`explain`输出将显示合并阶段：

```
{
  $lookup: {
    from: "otherCollection",
    as: "resultingArray",
    localField: "x",
    foreignField: "y",
    unwinding: { preserveNullAndEmptyArrays: false }
  }
}
```

## 例子

### $limit $skip $limit $skip 序列

止于Mongodb4.0

管道包含一系列交替的[$limit](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)和[$skip](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段：

```
{ $limit: 100 },
{ $skip: 5 },
{ $limit: 10 },
{ $skip: 2 }
```

[$skip $limit 序列优化](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)反转`{ $skip: 5 }`和`{ $limit: 10 }`阶段的位置并增加限制量：

```
{ $limit: 100 },
{ $limit: 15},
{ $skip: 5 },
{ $skip: 2 }
```

然后，优化器将两个[$limit](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段合并为一个[$limit](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段，将两个[$skip](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段合并为一个[$skip](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)阶段。结果序列如下：

```
{ $limit: 15 },
{ $skip: 7 }
```

有关详细信息，请参阅[$limit $limit 合并](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)和[$skip $skip 合并](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)。

> **\[success] 可以看看**
>
> [db.collection.aggregate()](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)中的[说明](/aggregation/aggregation-pipeline/aggregation-pipeline-optimization)选项

译者：李冠飞

校对：李冠飞


# 聚合管道限制

在本页面

* [结果大小限制](#result-size-restrictions)
* [Memory 限制](#memory-restrictions)

使用[聚合](/aggregation/aggregation-pipeline/aggregation-pipeline-limits)命令的聚合操作具有以下限制。

## 结果大小限制

Mongodb 3.6版本的改变：MongoDB 3.6 删除[聚合](/aggregation/aggregation-pipeline/aggregation-pipeline-limits)命令以将其结果作为单个文档返回的选项。

[聚合](/aggregation/aggregation-pipeline/aggregation-pipeline-limits)命令可以返回一个游标或将结果存储集合中。返回游标或将结果存储在集合中时，结果集中的每个文档都受[BSON 文件大小](/aggregation/aggregation-pipeline/aggregation-pipeline-limits)限制，目前为 16 兆字节;如果任何单个文档超过[BSON 文件大小](/aggregation/aggregation-pipeline/aggregation-pipeline-limits)限制，该命令将产生错误。该限制仅适用于返回的文件;在管道处理期间，文档可能超过此大小。 [db.collection.aggregate()](/aggregation/aggregation-pipeline/aggregation-pipeline-limits)方法默认返回游标。

## Memory 限制

管道阶段的 RAM 限制为 100M（100\*1024\*1024字节）。如果某个阶段超出此限制，MongoDB 将产生错误。要允许处理大型数据集，可以在`aggregate()`方法中设置`allowDiskUse`选项。`allowDiskUse`选项允许大多数聚合管道操作可以将数据写入临时文件。 以下聚合操作是`allowDiskUse`选项的例外； 这些操作必须在内存限制内：

* `$graphLookup`阶段
* `$group`阶段中使用的`$addToSet`累加器表达式（从版本4.2.3、4.0.14、3.6.17开始）
* `$group`阶段使用的`$push`累加器表达式(从版本4.2.3、4.0.14、3.6.17开始)

如果管道包含在`aggregate()`操作中观察`allowDiskUse: true`的其他阶段，那么`allowDiskUse: true`选项对这些其他阶段有效。

从MongoDB 4.2开始，如果任何聚合阶段由于内存限制而将数据写到临时文件，则分析器日志消息和诊断日志消息包括一个usedDisk指示器。

> **\[success] 可以看看**
>
> [$sort and Memory Restrictions](/aggregation/aggregation-pipeline/aggregation-pipeline-limits)和[$group Operator and Memory](/aggregation/aggregation-pipeline/aggregation-pipeline-limits)。

译者：李冠飞

校对：李冠飞


# 聚合管道和分片集合

在本页面

* [行为](#behavior)
* [优化](#optimization)

聚合管道支持对[分片](/aggregation/aggregation-pipeline/aggregation-pipeline-and-sharded-collections)集合的操作。本节介绍特定于[聚合管道](/aggregation/aggregation-pipeline)和分片集合的行为。

## 行为

Mongodb 3.2 版本的改变

如果管道以 shard key 上的精确[$match](/aggregation/aggregation-pipeline/aggregation-pipeline-and-sharded-collections)开头，则整个管道仅在匹配的分片上运行。以前，管道将被拆分，合并它的工作必须在主分片上完成。

对于必须在多个分片上运行的聚合操作，如果操作不需要在数据库的主分片上运行，则这些操作将会将结果路由到随机分片以合并结果，以避免该数据库的主分片超载。 [$out](/aggregation/aggregation-pipeline/aggregation-pipeline-and-sharded-collections)阶段和[$lookup](/aggregation/aggregation-pipeline/aggregation-pipeline-and-sharded-collections)阶段需要在数据库的主分片上运行。

## 优化

在将聚合管道分成两部分时，管道被拆分以确保分片在考虑优化的情况下执行尽可能多的阶段。

要查看管道是如何拆分的，请在[db.collection.aggregate()](/aggregation/aggregation-pipeline/aggregation-pipeline-and-sharded-collections)方法中包含[explain](/aggregation/aggregation-pipeline/aggregation-pipeline-and-sharded-collections)选项。

优化可能会在不同版本之间发生变化。

译者：李冠飞

校对：李冠飞


# 使用 Zip Code 数据集进行聚合

在本页面

* [数据模型 Data Model](#data-model)
* [aggregate()方法](#aggregate-method)
* [返回人口超过 1000 万的国家](#return-states-with-populations-above-10-million)
* [按 State 返回平均城市人口](#return-average-city-population-by-state)
* [按 State 返回最大和最小城市](#return-largest-and-smallest-cities-by-state)

本文档中的示例使用`zipcodes`集合。该系列可在以下网址获得：[media.mongodb.org/zips.json](http://media.mongodb.org/zips.json)。使用[mongoimport](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/docs/Reference/MongoDB-Package-Components/mongoimport.md)将此数据集加载到[mongod](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/docs/Reference/MongoDB-Package-Components/mongod.md)实例中。

## 数据模型

`zipcodes`集合中的每个文档都具有以下形式：

```
{
  "_id": "10280",
  "city": "NEW YORK",
  "state": "NY",
  "pop": 5574,
  "loc": [
    -74.016323,
    40.710537
  ]
}
```

* `_id`字段将 zip code 保存为 string。
* `city`字段包含 city name。一个城市可以有多个与之关联的 zip code，因为城市的不同部分可以各自具有不同的 zip code。
* `state`字段包含两个字母 state 缩写。
* `pop`字段包含人口。
* `loc`字段将位置保存为纬度经度对。

## aggregate()方法

以下所有示例都使用[mongo](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-program-mongo.html#db.collection.aggregate) shell 中的[aggregate()](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-method-db.collection.aggregate.html#bin.mongo)帮助程序。

[aggregate()](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-method-db.collection.aggregate.html#db.collection.aggregate)方法使用[聚合管道](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/core-aggregation-pipeline.html#id1)将文档处理为聚合结果。 [聚合管道](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/core-aggregation-pipeline.html#id1)由[多个阶段](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-pipeline.html#aggregation-pipeline-operator-reference)组成，每个阶段在文档沿着管道传递时都会对其进行处理。文档按顺序通过各个阶段。

[mongo](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-program-mongo.html#db.collection.aggregate) shell 中的[aggregate()](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-method-db.collection.aggregate.html#bin.mongo)方法在[聚合](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-command-aggregate.html#dbcmd.aggregate)数据库命令提供了一个包装器。有关用于数据聚合操作的更惯用的界面，请参阅[驱动](https://docs.mongodb.com/ecosystem/drivers)的文档。

## 返回人口超过 1000 万的国家

以下聚合操作将返回总人口超过 1000 万的所有州：

```
db.zipcodes.aggregate( [
    { $group: { _id: “$state“, totalPop: { $sum: “$pop“ } } },
    { $match: { totalPop: { $gte: 10*1000*1000 } } }
] )
```

在此 example 中，[聚合管道](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/core-aggregation-pipeline.html#id1)包含[$group](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-group.html#pipe._S_group)阶段，后跟[$match](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-match.html#pipe._S_match)阶段：

* 阶段按`state`字段对`zipcode`集合的文档进行分组，为每个 state 计算`totalPop`字段，并为每个唯一的 state 输出文档。

  新的 per-state 文档有两个字段：`_id`字段和`totalPop`字段。 `_id`字段包含`state`的 value即： group by field。 `totalPop`字段是一个计算字段，包含每个 state 的总人口。要计算 value，[$group](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-group.html#pipe._S_group)使用[$sum](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-sum.html#grp._S_sum) operator 为每个 state 添加填充字段(`pop`)。

  在[$group](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-group.html#pipe._S_group)阶段之后，管道中的文档类似于以下内容：

  ```
  {
      “_id“ : “AK“,
      “totalPop“ : 550043
  }
  ```
* [$match](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-match.html#pipe._S_match)阶段过滤这些分组文档，仅输出`totalPop` value 大于或等于 1000 万的文档。 [$match](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-match.html#pipe._S_match)阶段不会更改匹配的文档，但会不加修改地输出匹配的文档。

此聚合操作的等效[SQL](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-glossary.html#term-sql)是：

```sql
SELECT state, SUM(pop) AS totalPop
    FROM zipcodes
    GROUP BY state
    HAVING totalPop >= (10*1000*1000)
```

> **\[success] 也可以看看**
>
> [$group](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-group.html#pipe._S_group)，[$match](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-match.html#pipe._S_match)，[$sum](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-sum.html#grp._S_sum)

## 按 State 返回平均城市人口

以下聚合操作返回每个 state 中城市的平均人口数：

```
db.zipcodes.aggregate( [
    { $group: { _id: { state: “$state“, city: “$city“ }, pop: { $sum: “$pop“ } } },
    { $group: { _id: “$_id.state“, avgCityPop: { $avg: “$pop“ } } }
] )
```

在这个 example 中，[聚合管道](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/core-aggregation-pipeline.html#id1)包含[$group](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-group.html#pipe._S_group)阶段，后跟另一个[$group](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-group.html#pipe._S_group)阶段：

* 第一个阶段通过`city`和`state`的组合对文档进行分组，使用[$sum](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-sum.html#grp._S_sum)表达式计算每个组合的总体，并为每个`city`和`state`组合输出一个文档。 [\[1\]](#multiple-zips-per-city)

  在管道中的这个阶段之后，文档类似于以下内容：

  ```
  {
      “_id“ : {
          “state“ : “CO“,
          “city“ : “EDGEWATER“
      },
      “pop“ : 13154
  }
  ```
* 第二个[$group](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-group.html#pipe._S_group)阶段通过`_id.state`字段(i.e.`_id`文档中的`state`字段)对管道中的文档进行分组，使用[$avg](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-avg.html#grp._S_avg)表达式计算每个 state 的平均城市人口(`avgCityPop`)，并为每个 state 输出一个文档。

此聚合操作产生的文档类似于以下内容：

```
{
    “_id“ : “MN“,
    “avgCityPop“ : 5335
}
```

> **\[success] 也可以看看**
>
> [$group](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-group.html#pipe._S_group)，[$sum](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-sum.html#grp._S_sum)，[$avg](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-avg.html#grp._S_avg)

## 按 State 返回最大和最小城市

以下聚合操作按每个 state 的填充返回最小和最大的城市：

```
db.zipcodes.aggregate( [
    { 
        $group:{
            _id: { state: “$state“, city: “$city“ },
            pop: { $sum: “$pop“ }
        }
    },
    { $sort: { pop: 1 } },
    { 
        $group:{
            _id : “$_id.state“,
            biggestCity:  { $last: “$_id.city“ },
            biggestPop:   { $last: “$pop“ },
            smallestCity: { $first: “$_id.city“ },
            smallestPop:  { $first: “$pop“ }
        }
    },
    // the following $project is optional, and
    // modifies the output format.
    { 
        $project:{ 
            _id: 0,
            state: “$_id“,
            biggestCity:  { name: “$biggestCity“,  pop: “$biggestPop“ },
            smallestCity: { name: “$smallestCity“, pop: “$smallestPop“ }
        }
    }
] )
```

在此 example 中，[聚合管道](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/core-aggregation-pipeline.html#id1)包含[$group](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-group.html#pipe._S_group)阶段，`$sort`阶段，另一个[$group](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-group.html#pipe._S_group)阶段和`$project`阶段：

* 第一个[$group](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-group.html#pipe._S_group)阶段通过`city`和`state`的组合对文档进行分组，计算每个组合的`pop`值的[和](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-sum.html#grp._S_sum)，并为每个`city`和`state`组合输出一个文档。

  在管道的这个阶段，文档类似于以下内容：

  ```
  {
      “_id“ : {
          “state“ : “CO“,
          “city“ : “EDGEWATER“
      },
      “pop“ : 13154
  }
  ```
* [$sort](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-sort.html#pipe._S_sort)阶段通过`pop` field value 对管道中的文档进行排序，从最小到最大; 即：通过增加 order。此操作不会更改文档。
* 下一个[$group](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-group.html#pipe._S_group)阶段按`_id.state`字段(即：`_id`文档中的`state`字段)对 now-sorted 文档进行分组，并为每个 state 输出一个文档。

  该阶段还为每个 state 计算以下四个字段。使用[$last](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-last.html#grp._S_last)表达式，[$group](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-group.html#pipe._S_group) operator 创建`biggestCity`和`biggestPop`字段，用于存储人口和人口最多的城市。使用[$first](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-first.html#grp._S_first)表达式，[$group](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-group.html#pipe._S_group) operator 创建`smallestCity`和`smallestPop`字段，用于存储人口和人口最少的城市。

  在管道的这个阶段，文件类似于以下内容：

  ```
  {
      “_id“ : “WA“,
      “biggestCity“ : “SEATTLE“,
      “biggestPop“ : 520096,
      “smallestCity“ : “BENGE“,
      “smallestPop“ : 2
  }
  ```
* 最后的[$project](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-project.html#pipe._S_project)阶段将`_id`字段重命名为`state`，并将`biggestCity`，`biggestPop`，`smallestCity`和`smallestPop`移动到`biggestCity`和`smallestCity`嵌入文档中。

此聚合操作的输出文档类似于以下内容：

```
{
    “state“ : “RI“,
    “biggestCity“ : {
        “name“ : “CRANSTON“,
        “pop“ : 176404
    },
    “smallestCity“ : {
        “name“ : “CLAYVILLE“,
        “pop“ : 45
    }
}
```

|      |                                                      |
| ---- | ---------------------------------------------------- |
| \[1] | 一个城市可以有多个与之关联的 zip code，因为城市的不同部分可以各自具有不同的 zip code。 |

译者：李冠飞

校对：李冠飞


# 使用用户首选项数据进行聚合

在本页面

* [数据模型](#data-model)
* [规范化和排序文档](#normalize-and-sort-documents)
* [返回按月加入订单的用户名](#return-usernames-ordered-by-join-month)
* [返回每月的联接总数](#return-total-number-of-joins-per-month)
* [Return 五个 Common“喜欢”](#return-the-five-most-common-likes)

## 数据模型

考虑一个假设的体育俱乐部，其数据库包含一个`users`集合，用于跟踪用户的加入日期，运动偏好，并将这些数据存储在类似于以下内容的文档中：

```
{
    _id : “jane“,
    joined : ISODate(“2011-03-02“),
    likes : [“golf“, “racquetball“]
}
{
    _id : “joe“,
    joined : ISODate(“2012-07-02“),
    likes : [“tennis“, “golf“, “swimming“]
}
```

## 规范化和排序文档

以下操作以大写和字母 order 返回用户名。聚合包括`users`集合中所有文档的用户名。您可以这样做以规范化用户名以进行处理。

```
db.users.aggregate([
    { $project : { name:{$toUpper:“$_id“} , _id:0 } },
    { $sort : { name : 1 } }
])
```

`users`集合中的所有文档都通过管道传递，该管道包含以下操作：

* [$project](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-project.html#pipe._S_project) 操作：
  * 创建一个名为`name`的新字段。
  * 使用[$toUpper](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-toUpper.html#exp._S_toUpper) operator 将`_id`的 value 转换为大写。然后[$project](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-project.html#pipe._S_project)创建一个名为`name`的新字段来保存此 value。
  * 抑制`id`字段。除非明确禁止，否则[$project](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-project.html#pipe._S_project)将默认通过`_id`字段。
* operator 按`name`字段对结果进行排序。

聚合的结果类似于以下内容：

```
{
    "name" : "JANE"
},
{
    "name" : "JILL"
},
{
    "name" : "JOE"
}
```

## 返回按月加入订单的用户名

以下聚合操作返回按其加入的月份排序的用户名。这种聚合可以帮助生成会员续订通知。

```
db.users.aggregate([
    { $project :
        {
            month_joined : { $month : “$joined“ },
            name : “$_id“,
            _id : 0
        }
    },
    { $sort : { month_joined : 1 } }
])
```

管道通过以下操作传递`users`集合中的所有文档：

* [$project](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-project.html#pipe._S_project) operator：
  * 创建两个新字段：`month_joined`和`name`。
  * 从结果中抑制`id`。除非明确禁止，否则[aggregate()](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-method-db.collection.aggregate.html#db.collection.aggregate)方法包含`_id`。
* [$month](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-month.html#exp._S_month) operator 将`joined`字段的值转换为月份的 integer 表示。然后[$project](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-project.html#pipe._S_project) operator 将这些值分配给`month_joined`字段。
* [$sort](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-sort.html#pipe._S_sort) operator 按`month_joined`字段对结果进行排序。

该操作返回类似于以下内容的结果：

```
{
    “month_joined“ : 1,
    “name“ : “ruth“
},
{
    “month_joined“ : 1,
    “name“ : “harold“
},
{
    “month_joined“ : 1,
    “name“ : “kate“
},
{
    “month_joined“ : 2,
    “name“ : “jill“
}
```

## 返回每月的联接总数

以下操作显示了一年中每个月加入的人数。您可以将此汇总数据用于招聘和营销策略。

```
db.users.aggregate([
    { $project : { month_joined : { $month : “$joined“ } } } ,
    { $group : { _id : {month_joined:“$month_joined“} , number : { $sum : 1 } } },
    { $sort : { “_id.month_joined“ : 1 } }
])
```

管道通过以下操作传递`users`集合中的所有文档：

* [$project](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-project.html#pipe._S_project) operator 创建一个名为`month_joined`的新字段。
* [$month](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-month.html#exp._S_month) operator 将`joined`字段的值转换为月份的 integer 表示。然后[$project](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-project.html#pipe._S_project) operator 将值分配给`month_joined`字段。
* [$group](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-group.html#pipe._S_group) operator 收集具有给定`month_joined` value 的所有文档，并计算该 value 的文档数量。具体来说，对于每个唯一 value，[$group](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-group.html#pipe._S_group)创建一个包含两个字段的新“per-month”文档：
  * `_id`，包含带有`month_joined`字段及其 value 的嵌套文档。
  * `number`，这是一个生成的字段。对于包含给定`month_joined` value 的每个文档，[$sum](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-sum.html#grp._S_sum) operator 将此字段递增 1。
* [$sort](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-sort.html#pipe._S_sort) operator 根据`month_joined`字段的内容对[$group](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-group.html#pipe._S_group)创建的文档进行排序。

此聚合操作的结果类似于以下内容：

```
{
    “_id“ : {
        “month_joined“ : 1
    },
    “number“ : 3
},
{
    “_id“ : {
        “month_joined“ : 2
    },
    “number“ : 9
},
{
    “_id“ : {
        “month_joined“ : 3
    },
    “number“ : 5
}
```

## Return 五个 Common“喜欢”

以下聚合收集数据集中前五个最“喜欢”的活动。这种分析有助于规划和未来发展。

```
db.users.aggregate([
    { $unwind : “$likes“ },
    { $group : { _id : “$likes“ , number : { $sum : 1 } } },
    { $sort : { number : -1 } },
    { $limit : 5 }
])
```

管道从`users`集合中的所有文档开始，并通过以下操作传递这些文档：

* [$unwind](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-unwind.html#pipe._S_unwind) operator 分隔`likes` array 中的每个 value，并为 array 中的每个元素创建源文档的新 version。

> **\[success] 例子**
>
> 给出来自用户集合的以下文档：
>
> ```
> {
> _id : "jane",
> joined : ISODate("2011-03-02"),
> likes : ["golf", "racquetball"]
> }
> ```
>
> `$unwind`运算符将创建下列文件：
>
> ```
> {
>  _id : “jane“,
>  joined : ISODate(“2011-03-02“),
>  likes : “golf“
> }
> {
>  _id : “jane“,
>  joined : ISODate(“2011-03-02“),
>  likes : “racquetball“
> }
> ```

* [$group](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-group.html#pipe._S_group) operator 收集`likes`字段具有相同 value 的所有文档，并计算每个分组。有了这些信息，[$group](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-group.html#pipe._S_group)创建了一个包含两个字段的新文档：
  * `_id`，其中包含`likes` value。
  * `number`，这是一个生成的字段。对于包含给定`likes` value 的每个文档，[$sum](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-sum.html#grp._S_sum) operator 将此字段递增 1。
* [$sort](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-sort.html#pipe._S_sort) operator 按字段在 reverse order 中对这些文档进行排序。
* [$limit](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipeline/reference-operator-aggregation-limit.html#pipe._S_limit) operator 仅包含前 5 个结果文档。

聚合的结果类似于以下内容：

```
{
    “_id“ : “golf“,
    “number“ : 33
},
{
    “_id“ : “racquetball“,
    “number“ : 31
},
{
    “_id“ : “swimming“,
    “number“ : 24
},
{
    “_id“ : “handball“,
    “number“ : 19
},
{
    “_id“ : “tennis“,
    “number“ : 18
}
```

译者：李冠飞

校对：李冠飞


# Map-Reduce

在本页面

* [Map-Reduce JavaScript 函数](#map-reduce-javascript-functions)
* [Map-Reduce 行为](#map-reduce-results)
* [分片集合](#sharded-collections)
* [视图](#views)

Map-reduce 是一种数据处理范式，用于将大量数据压缩为有用的聚合结果。对于 map-reduce 操作，MongoDB 提供[MapReduce](/aggregation/map-reduce)数据库命令。

> **\[success] 注意**
>
> 从4.2版开始，MongoDB弃用：
>
> * 用于创建新分片集合的map-reduce选项，以及用于map-reduce的[分片](/aggregation/map-reduce)选项。若要输出到分片集合，请先创建分片集合。MongoDB 4.2也不赞成替换现有的分片集合。
> * [nonAtomic：false](/aggregation/map-reduce)选项的显式规范。

考虑以下 map-reduce 操作：

![带注释的 map-reduce 操作图。](https://docs.mongodb.com/manual/_images/map-reduce.bakedsvg.svg)

在此 map-reduce 操作中，MongoDB 将 map 阶段应用于每个输入文档(即：集合中与查询条件匹配的文档)。 map函数会发出 key-value 对。对于具有多个值的键，MongoDB 应用 reduce 阶段，该阶段收集并压缩聚合数据。然后 MongoDB 结果存储在一个集合中。可选地，reduce 函数的输出可以通过 finalize 函数以进一步压缩或处理聚合的结果。

MongoDB 中的所有 map-reduce 函数都是JavaScript，在mongod进程中运行。 Map-reduce 操作将单个[集合](/aggregation/map-reduce)的文档作为输入，并且可以在开始 map 阶段之前执行任意排序和限制。 [MapReduce](/aggregation/map-reduce)可以将map-reduce操作的结果作为文档返回，或者可以将结果写入集合。

> **\[success] 注意**
>
> 对于大多数聚合操作，[聚合管道](/aggregation/aggregation-pipeline)提供更好的性能和更一致的接口。但是，map-reduce 操作提供了一些在聚合管道中目前不可用的灵活性。

## Map-Reduce JavaScript 函数

在 MongoDB 中，map-reduce 操作使用自定义 JavaScript 函数将值映射或关联到一个键。如果一个键有多个值映射到它，则操作会将 键的值减少为单个对象。

自定义 JavaScript 函数的使用为 map-reduce 操作提供了灵活性。例如，在处理文档时，map 函数可以创建多个键和值映射或不创建映射。 Map-reduce 操作还可以使用自定义 JavaScript 函数对 map和reduce操作结束时的结果进行最终修改，例如执行其他计算。

在4.2.1版本开始，MongoDB的不支持在`map`，`reduce`和`finalize`中使用范围（即:[BSON type 15](/aggregation/map-reduce)）的JavaScript。要限定变量的范围，请使用`scope`参数。

## Map-Reduce 行为

在 MongoDB 中，map-reduce 操作可以将结果写入集合或内联返回结果。如果将 map-reduce 输出写入集合，则可以对同一输入集合执行后续 map-reduce 操作，这些集合将替换，合并或reduce新结果与先前结果合并。有关详细信息和示例，请参阅[MapReduce](/aggregation/map-reduce)和[执行增量 Map-Reduce](/aggregation/map-reduce)。

在内联返回 map-reduce 操作的结果时，结果文档必须在[BSON 文件大小](/aggregation/map-reduce)限制范围内，当前为 16 兆字节。有关 map-reduce 操作的限制和限制的其他信息，请参阅[MapReduce 参考](/aggregation/map-reduce) 页面。

## 分片集合

MongoDB 支持[分片集合](/aggregation/map-reduce)上的 map-reduce 操作。

但是，从版本4.2开始，MongoDB弃用map-reduce选项来\_创建\_新的分片集合，并将 `sharded`选项用于map-reduce。若要输出到分片集合，请首先创建分片集合。MongoDB 4.2不建议替换现有分片集合。

见[Map-Reduce and Sharded Collections](/aggregation/map-reduce/map-reduce-and-sharded-collections)。

## 视图

[视图](/aggregation/map-reduce)不支持 map-reduce 操作。

译者：李冠飞

校对：李冠飞


# Map-Reduce 和分片集合

在本页面

* [分片集合作为输入](#sharded-collection-as-input)
* [分片集合作为输出](#sharded-collection-as-output)

Map-reduce 支持对分片集合的操作，既可以作为输入也可以作为输出。本节介绍[MapReduce](/aggregation/map-reduce/map-reduce-and-sharded-collections)特定于分片集合的操作。

## 分片集合作为输入

当使用分片集合作为 map-reduce 操作的输入时，[mongos](/aggregation/map-reduce/map-reduce-and-sharded-collections)将自动将 map-reduce job 分派给 parallel 中的每个分片。不需要特殊选项。 [mongos](/aggregation/map-reduce/map-reduce-and-sharded-collections)将等待所有分片上的作业完成。

## 分片集合作为输出

如果[MapReduce](/aggregation/map-reduce/map-reduce-and-sharded-collections)的`out`字段具有`sharded` 值，则 MongoDB 使用`_id`字段将输出集合分片为分片键。

要输出到分片集合：

* 如果输出集合不存在，请首先创建分片集合

  从版本4.2开始，MongoDB弃用map-reduce选项以 \_创建\_新的分片集合，并将该`sharded` 选项用于map-reduce。因此，要输出到分片集合，请首先创建分片集合。

  如果您没有首先创建分片集合，则MongoDB会在`_id`字段上创建和分片集合。但是，建议您首先创建分片集合。
* 从4.2版开始，MongoDB不赞成替换现有的分片集合。
* 从版本4.0开始，如果输出集合已存在但未分片，则map-reduce失败。
* 对于新的或空的分片集合，MongoDB使用map-reduce操作的第一阶段的结果来创建在分片之间分布的初始块。
* [`mongos`](/aggregation/map-reduce/map-reduce-and-sharded-collections)并行地将映射减少后处理作业分派给拥有块的每个分片。在后处理期间，每个分片将从其他分片中提取其自身块的结果，运行最终的reduce / finalize，然后本地写入输出集合。

  > **注意**
  >
  > * 在以后的 map-reduce 作业中，MongoDB 根据需要拆分块。
  > * 在 post-processing 期间会自动阻止输出集合的块平衡，以避免并发问题。

译者：李冠飞

校对：小芒果


# Map-Reduce 并发

map-reduce 操作由许多任务组成，包括从输入集合中读取，执行`map` function，执行`reduce` function，在处理期间写入临时集合以及写入输出集合。

在操作期间，map-reduce 采用以下锁定：

* 读取阶段采用读锁定。它产生每 100 个文件。
* insert 进入临时集合会为单次写入执行写锁定。
* 如果输出集合不存在，则输出集合的创建将采用写入锁定。
* 如果输出集合存在，则输出操作(即：`merge`，`replace`，`reduce`)将执行写入锁定。此写锁定是 global，并阻止[mongod](/aggregation/map-reduce/map-reduce-concurrency)实例上的所有操作。

  > **注意**
  >
  > 后处理期间的最终写锁定使结果自动显示。然而，输出操作`merge`和`reduce`可能需要时间来处理。对于`merge`和`reduce`，该 `nonAtomic`标志可用，从而释放写入每个输出文档之间的锁定。从MongoDB 4.2开始，不推荐使用`nonAtomic: false`显式设置。有关[`db.collection.mapReduce()`](/aggregation/map-reduce/map-reduce-concurrency)更多信息，请参见参考。

译者：李冠飞

校对：


# Map-Reduce 示例

在本页面

* [返回每位客户的总价格](#return-the-total-price-per-customer)
* [用每个项目的平均数量计算订单和总数量](#calculate-order-and-total-quantity-with-average-quantity-per-item)

在[mongo](/aggregation/map-reduce/map-reduce-examples) shell 中，[db.collection.mapReduce()](/aggregation/map-reduce/map-reduce-examples)方法是[MapReduce](/aggregation/map-reduce/map-reduce-examples)命令周围的 wrapper。以下示例使用[db.collection.mapReduce()](/aggregation/map-reduce/map-reduce-examples)方法：

> **聚合管道作为替代**
>
> [聚合管道](/aggregation/map-reduce/map-reduce-examples) 比map-reduce提供更好的性能和更一致的接口。
>
> 各种map-reduce表达式可以使用被重写[聚合管道运算符](/aggregation/map-reduce/map-reduce-examples)，诸如[`$group`](/aggregation/map-reduce/map-reduce-examples)， [`$merge`](/aggregation/map-reduce/map-reduce-examples)等
>
> 下面的示例包括聚合管道备选方案。

`orders`使用以下文档创建样本集合：

```
db.orders.insertMany([
   { _id: 1, cust_id: "Ant O. Knee", ord_date: new Date("2020-03-01"), price: 25, items: [ { sku: "oranges", qty: 5, price: 2.5 }, { sku: "apples", qty: 5, price: 2.5 } ], status: "A" },
   { _id: 2, cust_id: "Ant O. Knee", ord_date: new Date("2020-03-08"), price: 70, items: [ { sku: "oranges", qty: 8, price: 2.5 }, { sku: "chocolates", qty: 5, price: 10 } ], status: "A" },
   { _id: 3, cust_id: "Busby Bee", ord_date: new Date("2020-03-08"), price: 50, items: [ { sku: "oranges", qty: 10, price: 2.5 }, { sku: "pears", qty: 10, price: 2.5 } ], status: "A" },
   { _id: 4, cust_id: "Busby Bee", ord_date: new Date("2020-03-18"), price: 25, items: [ { sku: "oranges", qty: 10, price: 2.5 } ], status: "A" },
   { _id: 5, cust_id: "Busby Bee", ord_date: new Date("2020-03-19"), price: 50, items: [ { sku: "chocolates", qty: 5, price: 10 } ], status: "A"},
   { _id: 6, cust_id: "Cam Elot", ord_date: new Date("2020-03-19"), price: 35, items: [ { sku: "carrots", qty: 10, price: 1.0 }, { sku: "apples", qty: 10, price: 2.5 } ], status: "A" },
   { _id: 7, cust_id: "Cam Elot", ord_date: new Date("2020-03-20"), price: 25, items: [ { sku: "oranges", qty: 10, price: 2.5 } ], status: "A" },
   { _id: 8, cust_id: "Don Quis", ord_date: new Date("2020-03-20"), price: 75, items: [ { sku: "chocolates", qty: 5, price: 10 }, { sku: "apples", qty: 10, price: 2.5 } ], status: "A" },
   { _id: 9, cust_id: "Don Quis", ord_date: new Date("2020-03-20"), price: 55, items: [ { sku: "carrots", qty: 5, price: 1.0 }, { sku: "apples", qty: 10, price: 2.5 }, { sku: "oranges", qty: 10, price: 2.5 } ], status: "A" },
   { _id: 10, cust_id: "Don Quis", ord_date: new Date("2020-03-23"), price: 25, items: [ { sku: "oranges", qty: 10, price: 2.5 } ], status: "A" }
])
```

## 返回每位客户的总价格

对`orders`集合执行map-reduce操作，以对进行分组`cust_id`，并计算`price`每个的 的总和`cust_id`：

1. 定义map函数来处理每个输入文档：
2. 在函数中，`this`指的是map-reduce操作正在处理的文档。
3. 该函数将映射`price`到`cust_id`每个文档的，并发出`cust_id`和`price`对。

```
var mapFunction1 = function() {
   emit(this.cust_id, this.price);
};
```

1. 使用两个参数`keyCustId`和定义相应的reduce函数 `valuesPrices`：
2. `valuesPrices`是一个数组，其元素是`price` 由map功能发射并由分组值`keyCustId`。
3. 该函数将`valuesPrice`数组简化为其元素的总和。

```
var reduceFunction1 = function(keyCustId, valuesPrices) {
   return Array.sum(valuesPrices);
};
```

1. `orders`使用`mapFunction1`map函数和`reduceFunction1` reduce函数对集合中的所有文档执行map-reduce 。

```
db.orders.mapReduce(
   mapFunction1,
   reduceFunction1,
   { out: "map_reduce_example" }
)
```

此操作将结果输出到名为的集合 `map_reduce_example`。如果`map_reduce_example`集合已经存在，则该操作将用此map-reduce操作的结果替换内容。

1. 查询`map_reduce_example`集合以验证结果：

```
db.map_reduce_example.find().sort( { _id: 1 } )
```

​ 该操作返回以下文档：

```
{ "_id" : "Ant O. Knee", "value" : 95 }
{ "_id" : "Busby Bee", "value" : 125 }
{ "_id" : "Cam Elot", "value" : 60 }
{ "_id" : "Don Quis", "value" : 155 }
```

### 聚合替代

使用可用的聚合管道运算符，您可以重写map-reduce操作，而无需定义自定义函数：

```
db.orders.aggregate([
   { $group: { _id: "$cust_id", value: { $sum: "$price" } } },
   { $out: "agg_alternative_1" }
])
```

1. [`$group`](/aggregation/map-reduce/map-reduce-examples)由平台组`cust_id`并计算`value`字段（参见`$sum`）。该 `value`字段包含`price`每个的总计`cust_id`。

   该阶段将以下文档输出到下一阶段：

   ```
   { "_id" : "Don Quis", "value" : 155 }
   { "_id" : "Ant O. Knee", "value" : 95 }
   { "_id" : "Cam Elot", "value" : 60 }
   { "_id" : "Busby Bee", "value" : 125 }
   ```
2. 然后，[`$out`](/aggregation/map-reduce/map-reduce-examples)将输出写入collection `agg_alternative_1`。或者，您可以使用 [`$merge`](/aggregation/map-reduce/map-reduce-examples)代替[`$out`](/aggregation/map-reduce/map-reduce-examples)。
3. 查询`agg_alternative_1`集合以验证结果：

   ```
   db.agg_alternative_1.find().sort( { _id: 1 } )
   ```

   该操作返回以下文档：

   ```
   { "_id" : "Ant O. Knee", "value" : 95 }
   { "_id" : "Busby Bee", "value" : 125 }
   { "_id" : "Cam Elot", "value" : 60 }
   { "_id" : "Don Quis", "value" : 155 }
   ```

## 用每个项目的平均数量计算订单和总数量

在此示例中，您将对值大于或等于的`orders`所有文档在集合上执行map-reduce操作 。工序按字段分组 ，并计算每个的订单数量和总订购量。然后，该操作将为每个值计算每个订单的平均数量，并将结果合并到输出集合中。合并结果时，如果现有文档的密钥与新结果相同，则该操作将覆盖现有文档。如果不存在具有相同密钥的文档，则该操作将插入该文档。

1. 定义map函数来处理每个输入文档：

   * 在函数中，`this`指的是map-reduce操作正在处理的文档。
   * 对于每个商品，该函数将其`sku`与一个新对象相关联，该对象`value`包含订单的`count`of `1`和该商品`qty`，并发出`sku`and `value`对。

   ```
   var mapFunction2 = function() {
       for (var idx = 0; idx < this.items.length; idx++) {
          var key = this.items[idx].sku;
          var value = { count: 1, qty: this.items[idx].qty };

          emit(key, value);
       }
   };
   ```
2. 使用两个参数`keySKU`和定义相应的reduce函数 `countObjVals`：

   * `countObjVals`是一个数组，其元素是映射到`keySKU`由map函数传递给reducer函数的分组值的对象。
   * 该函数将`countObjVals`数组简化为`reducedValue`包含`count`和 `qty`字段的单个对象。
   * 在中`reducedVal`，该`count`字段包含 `count`各个数组元素的`qty`字段总和，而该字段包含各个数组元素的 字段总和`qty`。

   ```
   var reduceFunction2 = function(keySKU, countObjVals) {
      reducedVal = { count: 0, qty: 0 };

      for (var idx = 0; idx < countObjVals.length; idx++) {
          reducedVal.count += countObjVals[idx].count;
          reducedVal.qty += countObjVals[idx].qty;
      }

      return reducedVal;
   };
   ```
3. 定义有两个参数的函数确定`key`和 `reducedVal`。该函数修改`reducedVal`对象以添加一个名为`avg`的计算字段，并返回修改后的对象：

   ```
   var finalizeFunction2 = function (key, reducedVal) {
     reducedVal.avg = reducedVal.qty/reducedVal.count;
     return reducedVal;
   };
   ```
4. 在执行的map-reduce操作`orders`使用集合`mapFunction2`，`reduceFunction2`和 `finalizeFunction2`功能。

   ```
   db.orders.mapReduce(
      mapFunction2,
      reduceFunction2,
      {
        out: { merge: "map_reduce_example2" },
        query: { ord_date: { $gte: new Date("2020-03-01") } },
        finalize: finalizeFunction2
      }
    );
   ```

   此操作使用该`query`字段选择仅`ord_date`大于或等于的那些文档。然后将结果输出到集合 。`new Date("2020-03-01")` `map_reduce_example2`

   如果`map_reduce_example2`集合已经存在，则该操作会将现有内容与此map-reduce操作的结果合并。也就是说，如果现有文档具有与新结果相同的密钥，则该操作将覆盖现有文档。如果不存在具有相同密钥的文档，则该操作将插入该文档。
5. 查询`map_reduce_example2`集合以验证结果：

   ```
   db.map_reduce_example2.find().sort( { _id: 1 } )
   ```

   该操作返回以下文档：

   ```
   { "_id" : "apples", "value" : { "count" : 3, "qty" : 30, "avg" : 10 } }
   { "_id" : "carrots", "value" : { "count" : 2, "qty" : 15, "avg" : 7.5 } }
   { "_id" : "chocolates", "value" : { "count" : 3, "qty" : 15, "avg" : 5 } }
   { "_id" : "oranges", "value" : { "count" : 6, "qty" : 58, "avg" : 9.666666666666666 } }
   { "_id" : "pears", "value" : { "count" : 1, "qty" : 10, "avg" : 10 } }
   ```

## 聚合替代

使用可用的聚合管道运算符，您可以重写map-reduce操作，而无需定义自定义函数：

```
   db.orders.aggregate( [
      { $match: { ord_date: { $gte: new Date("2020-03-01") } } },
      { $unwind: "$items" },
      { $group: { _id: "$items.sku", qty: { $sum: "$items.qty" }, orders_ids: { $addToSet: "$_id" } }  },
      { $project: { value: { count: { $size: "$orders_ids" }, qty: "$qty", avg: { $divide: [ "$qty", { $size: "$orders_ids" } ] } } } },
      { $merge: { into: "agg_alternative_3", on: "_id", whenMatched: "replace",  whenNotMatched: "insert" } }
   ] )
```

1. 该[`$match`](/aggregation/map-reduce/map-reduce-examples)阶段仅选择`ord_date`大于或等于`new Date("2020-03-01")`的那些文档。
2. 该`$unwinds`阶段按`items`数组字段细分文档，以输出每个数组元素的文档。例如：

   ```
      { "_id" : 1, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-01T00:00:00Z"), "price" : 25, "items" : { "sku" : "oranges", "qty" : 5, "price" : 2.5 }, "status" : "A" }
      { "_id" : 1, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-01T00:00:00Z"), "price" : 25, "items" : { "sku" : "apples", "qty" : 5, "price" : 2.5 }, "status" : "A" }
      { "_id" : 2, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 70, "items" : { "sku" : "oranges", "qty" : 8, "price" : 2.5 }, "status" : "A" }
      { "_id" : 2, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 70, "items" : { "sku" : "chocolates", "qty" : 5, "price" : 10 }, "status" : "A" }
      { "_id" : 3, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 50, "items" : { "sku" : "oranges", "qty" : 10, "price" : 2.5 }, "status" : "A" }
      { "_id" : 3, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 50, "items" : { "sku" : "pears", "qty" : 10, "price" : 2.5 }, "status" : "A" }
      { "_id" : 4, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-18T00:00:00Z"), "price" : 25, "items" : { "sku" : "oranges", "qty" : 10, "price" : 2.5 }, "status" : "A" }
      { "_id" : 5, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-19T00:00:00Z"), "price" : 50, "items" : { "sku" : "chocolates", "qty" : 5, "price" : 10 }, "status" : "A" }
      ...
   ```
3. [`$group`](/aggregation/map-reduce/map-reduce-examples)由平台组`items.sku`，计算每个SKU：
   * 该`qty`字段。该`qty`字段包含`qty`每个订单的总数`items.sku`（请参阅参考资料`$sum`）。
   * `orders_ids`列表。该`orders_ids`字段包含不同顺序的列表`_id`的对`items.sku`（参见 `$addToSet`）。

     ```
     { "_id" : "chocolates", "qty" : 15, "orders_ids" : [ 2, 5, 8 ] }
     { "_id" : "oranges", "qty" : 63, "orders_ids" : [ 4, 7, 3, 2, 9, 1, 10 ] }
     { "_id" : "carrots", "qty" : 15, "orders_ids" : [ 6, 9 ] }
     { "_id" : "apples", "qty" : 35, "orders_ids" : [ 9, 8, 1, 6 ] }
     { "_id" : "pears", "qty" : 10, "orders_ids" : [ 3 ] }
     ```
4. 该[`$project`](/aggregation/map-reduce/map-reduce-examples)阶段调整输出文档的形状以反映map-reduce的输出，该输出具有两个字段`_id`和 `value`。该[`$project`](/aggregation/map-reduce/map-reduce-examples)设置：
   * `value.count`到的尺寸`orders_ids`数组。（请参阅[`$size`](/aggregation/map-reduce/map-reduce-examples)）
   * 在`value.qty`到`qty`输入文档的数量字段。
   * `value.avg`平均每笔订购的数量。（请参阅[`$divide`](/aggregation/map-reduce/map-reduce-examples)和[`$size`](/aggregation/map-reduce/map-reduce-examples)）

     ```
     { "_id" : "apples", "value" : { "count" : 4, "qty" : 35, "avg" : 8.75 } }
     { "_id" : "pears", "value" : { "count" : 1, "qty" : 10, "avg" : 10 } }
     { "_id" : "chocolates", "value" : { "count" : 3, "qty" : 15, "avg" : 5 } }
     { "_id" : "oranges", "value" : { "count" : 7, "qty" : 63, "avg" : 9 } }
     { "_id" : "carrots", "value" : { "count" : 2, "qty" : 15, "avg" : 7.5 } }
     ```
5. 最后，[`$merge`](/aggregation/map-reduce/map-reduce-examples)将输出写入collection `agg_alternative_3`。如果现有文档的密钥`_id`与新结果相同，则该操作将覆盖现有文档。如果不存在具有相同密钥的文档，则该操作将插入该文档。
6. 查询`agg_alternative_3`集合以验证结果：

   ```
    db.agg_alternative_3.find().sort( { _id: 1 } )
   ```

   该操作返回以下文档：

   ```
    { "_id" : "apples", "value" : { "count" : 4, "qty" : 35, "avg" : 8.75 } }
    { "_id" : "carrots", "value" : { "count" : 2, "qty" : 15, "avg" : 7.5 } }
    { "_id" : "chocolates", "value" : { "count" : 3, "qty" : 15, "avg" : 5 } }
    { "_id" : "oranges", "value" : { "count" : 7, "qty" : 63, "avg" : 9 } }
    { "_id" : "pears", "value" : { "count" : 1, "qty" : 10, "avg" : 10 } }
   ```

译者：李冠飞

校对：


# 执行增量 Map-Reduce

在本页面

* [数据设置](#data-setup)
* [当前集合的初始 Map-Reduce](#initial-map-reduce-of-current-collection)
* [后续增量 Map-Reduce](#subsequent-incremental-map-reduce)

Map-reduce 操作可以处理复杂的聚合任务。要执行 map-reduce 操作，MongoDB 提供[MapReduce](/aggregation/map-reduce/perform-incremental-map-reduce)命令，并在[mongo](/aggregation/map-reduce/perform-incremental-map-reduce) shell 中提供[db.collection.mapReduce()](/aggregation/map-reduce/perform-incremental-map-reduce) wrapper 方法。

如果 map-reduce 数据集不断增长，您可能希望执行增量 map-reduce 而不是每个 time 对整个数据集执行 map-reduce 操作。

执行增量 map-reduce：

* 在当前集合上运行 map-reduce job 并将结果输出到单独的集合。
* 如果有更多数据要进行 process，run 后续 map-reduce job：
  * `query`参数指定仅匹配新文档的条件。
  * `out`参数，指定将新结果合并到现有输出集合中的`reduce`操作。

请考虑以下 example，其中您在`sessions`集合上安排 map-reduce 操作，以在每天结束时运行 run。

## 数据设置

`sessions`集合包含 log 用户每天会话的文档，例如：

```
db.sessions.save( { userid: "a", ts: ISODate('2011-11-03 14:17:00'), length: 95 } );
db.sessions.save( { userid: "b", ts: ISODate('2011-11-03 14:23:00'), length: 110 } );
db.sessions.save( { userid: "c", ts: ISODate('2011-11-03 15:02:00'), length: 120 } );
db.sessions.save( { userid: "d", ts: ISODate('2011-11-03 16:45:00'), length: 45 } );

db.sessions.save( { userid: "a", ts: ISODate('2011-11-04 11:05:00'), length: 105 } );
db.sessions.save( { userid: "b", ts: ISODate('2011-11-04 13:14:00'), length: 120 } );
db.sessions.save( { userid: "c", ts: ISODate('2011-11-04 17:00:00'), length: 130 } );
db.sessions.save( { userid: "d", ts: ISODate('2011-11-04 15:37:00'), length: 65 } );
```

## 当前集合的初始 Map-Reduce

运行第一个 map-reduce 操作如下：

* 定义 map function \_将`userid`映射到包含字段`userid`，`total_time`，`count`和`avg_time`的 object：

  ```
  var mapFunction = function() {
      var key = this.userid;
      var value = {
          userid: this.userid,
          total_time: this.length,
          count: 1,
          avg_time: 0
      };
      emit( key, value );
  };
  ```
* 使用两个 arguments `key`和`values`定义相应的 reduce function 以计算总 time 和计数。 `key`对应于`userid`，`values`是 array，其元素对应于映射到`mapFunction`中`userid`的各个 object。

  ```
  var reduceFunction = function(key, values) {
      var reducedObject = {
          userid: key,
          total_time: 0,
          count:0,
          avg_time:0
      };

      values.forEach( function(value) {
          reducedObject.total_time += value.total_time;
          reducedObject.count += value.count;
      });
      return reducedObject;
  };
  ```
* 使用两个 arguments `key`和`reducedValue`定义 finalize function。 function 修改`reducedValue`文档以添加另一个字段`average`并返回修改后的文档。

  ```
  var finalizeFunction = function (key, reducedValue) {
      if (reducedValue.count > 0)
          reducedValue.avg_time = reducedValue.total_time / reducedValue.count;

      return reducedValue;
  };
  ```
* 使用`mapFunction`，`reduceFunction`和`finalizeFunction`函数在`session`集合上执行 map-reduce。将结果输出到集合`session_stat`。如果`session_stat`集合已存在，则操作将替换内容：

  ```
  db.sessions.mapReduce( mapFunction,
      reduceFunction,
      {
          out: "session_stat",
          finalize: finalizeFunction
      }
  )
  ```
* 查询`session_stats`集合以验证结果：

  ```
  db.session_stats.find().sort( { _id: 1 } )
  ```

  该操作返回以下文档：

  ```
  { "_id" : "a", "value" : { "total_time" : 200, "count" : 2, "avg_time" : 100 } }
  { "_id" : "b", "value" : { "total_time" : 230, "count" : 2, "avg_time" : 115 } }
  { "_id" : "c", "value" : { "total_time" : 250, "count" : 2, "avg_time" : 125 } }
  { "_id" : "d", "value" : { "total_time" : 110, "count" : 2, "avg_time" : 55 } }
  ```

## 后续增量 Map-Reduce

之后，随着`sessions`集合的增长，您可以运行其他 map-reduce 操作。对于 example，将新文档添加到`sessions`集合：

```
db.sessions.save( { userid: "a", ts: ISODate('2011-11-05 14:17:00'), length: 100 } );
db.sessions.save( { userid: "b", ts: ISODate('2011-11-05 14:23:00'), length: 115 } );
db.sessions.save( { userid: "c", ts: ISODate('2011-11-05 15:02:00'), length: 125 } );
db.sessions.save( { userid: "d", ts: ISODate('2011-11-05 16:45:00'), length: 55 } );
```

最终，对`usersessions`集合执行增量map-reduce ，但使用该`query`字段仅选择新文档。将结果输出到collection `session_stats`，但是`reduce`将内容与增量map-reduce的结果进行比较：

```
db.usersessions.mapReduce(
   mapFunction,
   reduceFunction,
   {
     query: { ts: { $gte: ISODate('2020-03-05 00:00:00') } },
     out: { reduce: "session_stats" },
     finalize: finalizeFunction
   }
);
```

查询`session_stats`集合以验证结果：

```
db.session_stats.find().sort( { _id: 1 } )
```

该操作返回以下文档：

```
{ "_id" : "a", "value" : { "total_time" : 330, "count" : 3, "avg_time" : 110 } }
{ "_id" : "b", "value" : { "total_time" : 270, "count" : 3, "avg_time" : 90 } }
{ "_id" : "c", "value" : { "total_time" : 360, "count" : 3, "avg_time" : 120 } }
{ "_id" : "d", "value" : { "total_time" : 210, "count" : 3, "avg_time" : 70 } }
```

## 聚合替代

前提条件：将集合设置为原始状态：

```
db.usersessions.drop();

db.usersessions.insertMany([
   { userid: "a", start: ISODate('2020-03-03 14:17:00'), length: 95 },
   { userid: "b", start: ISODate('2020-03-03 14:23:00'), length: 110 },
   { userid: "c", start: ISODate('2020-03-03 15:02:00'), length: 120 },
   { userid: "d", start: ISODate('2020-03-03 16:45:00'), length: 45 },
   { userid: "a", start: ISODate('2020-03-04 11:05:00'), length: 105 },
   { userid: "b", start: ISODate('2020-03-04 13:14:00'), length: 120 },
   { userid: "c", start: ISODate('2020-03-04 17:00:00'), length: 130 },
   { userid: "d", start: ISODate('2020-03-04 15:37:00'), length: 65 }
])
```

使用可用的聚合管道运算符，您可以重写map-reduce示例，而无需定义自定义函数：

```
db.usersessions.aggregate([
   { $group: { _id: "$userid", total_time: { $sum: "$length" }, count: { $sum: 1 }, avg_time: { $avg: "$length" } } },
   { $project: { value: { total_time: "$total_time", count: "$count", avg_time: "$avg_time" } } },
   { $merge: {
      into: "session_stats_agg",
      whenMatched: [ { $set: {
         "value.total_time": { $add: [ "$value.total_time", "$$new.value.total_time" ] },
         "value.count": { $add: [ "$value.count", "$$new.value.count" ] },
         "value.avg": { $divide: [ { $add: [ "$value.total_time", "$$new.value.total_time" ] },  { $add: [ "$value.count", "$$new.value.count" ] } ] }
      } } ],
      whenNotMatched: "insert"
   }}
])
```

1. 通过`userid`[`$group`](/aggregation/map-reduce/perform-incremental-map-reduce)，得出：

   * `total_time`使用`$sum`操作
   * `count`使用`$sum`操作
   * `avg_time`使用[`$avg`](/aggregation/map-reduce/perform-incremental-map-reduce)操作

   该操作返回以下文档：

   ```
   { "_id" : "c", "total_time" : 250, "count" : 2, "avg_time" : 125 }
   { "_id" : "d", "total_time" : 110, "count" : 2, "avg_time" : 55 }
   { "_id" : "a", "total_time" : 200, "count" : 2, "avg_time" : 100 }
   { "_id" : "b", "total_time" : 230, "count" : 2, "avg_time" : 115 }
   ```
2. 该[`$project`](/aggregation/map-reduce/perform-incremental-map-reduce)阶段调整输出文档的形状以反映map-reduce的输出，该输出具有两个字段`_id`和 `value`。如果不需要镜像`_id`and `value`结构，则该阶段是可选的 。

   ```
   { "_id" : "a", "value" : { "total_time" : 200, "count" : 2, "avg_time" : 100 } }
   { "_id" : "d", "value" : { "total_time" : 110, "count" : 2, "avg_time" : 55 } }
   { "_id" : "b", "value" : { "total_time" : 230, "count" : 2, "avg_time" : 115 } }
   { "_id" : "c", "value" : { "total_time" : 250, "count" : 2, "avg_time" : 125 } }
   ```
3. 该[`$merge`](/aggregation/map-reduce/perform-incremental-map-reduce)阶段将结果输出到 `session_stats_agg`集合。如果现有文档`_id`与新结果相同，则该操作将应用指定的管道，以根据结果和现有文档计算total\_time，count和avg\_time。如果是相同的，现有的文档`_id`中`session_stats_agg`，操作插入文档。
4. 查询`session_stats_agg`集合以验证结果：

   ```
   db.session_stats_agg.find().sort( { _id: 1 } )
   ```

   该操作返回以下文档：

   ```
   { "_id" : "a", "value" : { "total_time" : 200, "count" : 2, "avg_time" : 100 } }
   { "_id" : "b", "value" : { "total_time" : 230, "count" : 2, "avg_time" : 115 } }
   { "_id" : "c", "value" : { "total_time" : 250, "count" : 2, "avg_time" : 125 } }
   { "_id" : "d", "value" : { "total_time" : 110, "count" : 2, "avg_time" : 55 } }
   ```
5. 新文档添加到`usersessions`集合中：

   ```
   db.usersessions.insertMany([
      { userid: "a", ts: ISODate('2020-03-05 14:17:00'), length: 130 },
      { userid: "b", ts: ISODate('2020-03-05 14:23:00'), length: 40 },
      { userid: "c", ts: ISODate('2020-03-05 15:02:00'), length: 110 },
      { userid: "d", ts: ISODate('2020-03-05 16:45:00'), length: 100 }
   ])
   ```
6. [`$match`](/aggregation/map-reduce/perform-incremental-map-reduce)在管道的开头添加一个阶段以指定日期过滤器：

   ```
   db.usersessions.aggregate([
      { $match: { ts: { $gte: ISODate('2020-03-05 00:00:00') } } },
      { $group: { _id: "$userid", total_time: { $sum: "$length" }, count: { $sum: 1 }, avg_time: { $avg: "$length" } } },
      { $project: { value: { total_time: "$total_time", count: "$count", avg_time: "$avg_time" } } },
      { $merge: {
         into: "session_stats_agg",
         whenMatched: [ { $set: {
            "value.total_time": { $add: [ "$value.total_time", "$$new.value.total_time" ] },
            "value.count": { $add: [ "$value.count", "$$new.value.count" ] },
            "value.avg_time": { $divide: [ { $add: [ "$value.total_time", "$$new.value.total_time" ] },  { $add: [ "$value.count", "$$new.value.count" ] } ] }
         } } ],
         whenNotMatched: "insert"
      }}
   ])
   ```
7. 查询`session_stats_agg`集合以验证结果：

   ```
   db.session_stats_agg.find().sort( { _id: 1 } )
   ```

   该操作返回以下文档：

   ```
   { "_id" : "a", "value" : { "total_time" : 330, "count" : 3, "avg_time" : 110 } }
   { "_id" : "b", "value" : { "total_time" : 270, "count" : 3, "avg_time" : 90 } }
   { "_id" : "c", "value" : { "total_time" : 360, "count" : 3, "avg_time" : 120 } }
   { "_id" : "d", "value" : { "total_time" : 210, "count" : 3, "avg_time" : 70 } }
   ```
8. 可选的。为了避免[`$match`](/aggregation/map-reduce/perform-incremental-map-reduce)每次运行时都必须修改聚合管道的日期条件，可以在帮助函数中定义包装聚合：

   ```
   updateSessionStats = function(startDate) {
      db.usersessions.aggregate([
         { $match: { ts: { $gte: startDate } } },
         { $group: { _id: "$userid", total_time: { $sum: "$length" }, count: { $sum: 1 }, avg_time: { $avg: "$length" } } },
         { $project: { value: { total_time: "$total_time", count: "$count", avg_time: "$avg_time" } } },
         { $merge: {
            into: "session_stats_agg",
            whenMatched: [ { $set: {
               "value.total_time": { $add: [ "$value.total_time", "$$new.value.total_time" ] },
               "value.count": { $add: [ "$value.count", "$$new.value.count" ] },
               "value.avg_time": { $divide: [ { $add: [ "$value.total_time", "$$new.value.total_time" ] },  { $add: [ "$value.count", "$$new.value.count" ] } ] }
            } } ],
            whenNotMatched: "insert"
         }}
      ]);
   };
   ```

   然后，要运行，您只需将开始日期传递给该`updateSessionStats()`函数：

   ```
   updateSessionStats(ISODate('2020-03-05 00:00:00'))
   ```

也可以看看

* [$ merge示例](/aggregation/map-reduce/perform-incremental-map-reduce)
* [按需实例化视图](/aggregation/map-reduce/perform-incremental-map-reduce)

译者：李冠飞

校对：


# 对 Map Function 进行故障排除

`map` function 是一个 JavaScript function，它将 value 与 key 关联或“maps”，并在[map-reduce](/aggregation/map-reduce/troubleshoot-the-map-function)操作期间发出 key 和 value 对。

要验证`map` function 发出的`key`和`value`对，请编写自己的`emit` function。

考虑一个包含以下原型文档的集合`orders`：

```
{
     _id: ObjectId("50a8240b927d5d8b5891743c"),
     cust_id: "abc123",
     ord_date: new Date("Oct 04, 2012"),
     status: 'A',
     price: 250,
     items: [ { sku: "mmm", qty: 5, price: 2.5 },
              { sku: "nnn", qty: 5, price: 2.5 } ]
}
```

* 为每个文档定义\_ma 功能

  ```
  var map = function() {
      emit(this.cust_id, this.price);
  };
  ```
* 定义`emit` function 以打印 key 和 value：

  ```
    var emit = function(key, value) {
        print("emit");
        print("key: " + key + "  value: " + tojson(value));
    }
  ```
* 使用`orders`集合中的单个文档调用`map` function：

  ```
    var myDoc = db.orders.findOne( { _id: ObjectId("50a8240b927d5d8b5891743c") } );
    map.apply(myDoc);
  ```
* 验证 key 和 value 对是否符合预期。

  ```
    emit
    key: abc123 value:250
  ```
* 使用`orders`集合中的多个文档调用`map` function：

  ```
    var myCursor = db.orders.find( { cust_id: "abc123" } );
    while (myCursor.hasNext()) {
        var doc = myCursor.next();
        print ("document _id= " + tojson(doc._id));
        map.apply(doc);
        print();
    }
  ```
* 验证 key 和 value 对是否符合预期。

> **也可以看看**
>
> map`function 必须满足各种要求。有关`map\` function 的所有要求的列表，请参阅[MapReduce](/aggregation/map-reduce/troubleshoot-the-map-function)或[mongo](/aggregation/map-reduce/troubleshoot-the-map-function) shell 辅助方法[db.collection.mapReduce()](/aggregation/map-reduce/troubleshoot-the-map-function)。

译者：李冠飞

校对：


# 排除 Reduce Function 问题

在本页面

* [确认输出类型](#confirm-output-type)
* [确保对映射值的 Order 不敏感](#ensure-insensitivity-to-the-order-of-mapped-values)
* [确保减少 Function Idempotence](#ensure-reduce-function-idempotence)

`reduce` function 是一个 JavaScript function，它在[map-reduce](/aggregation/map-reduce/troubleshoot-the-reduce-function)操作期间“减少”到单个 object 与特定 key 关联的所有值。 `reduce` function 必须满足各种要求。本教程有助于验证`reduce` function 是否符合以下条件：

* `reduce` function 必须\_retject 一个 object，其类型必须**与`map` function 发出的`value`的类型相同**。
* `valuesArray`中元素的 order 不应影响`reduce` function 的输出。
* `reduce` function 必须是幂等的。

有关`reduce` function 的所有要求的列表，请参阅[MapReduce](/aggregation/map-reduce/troubleshoot-the-reduce-function)或[mongo](/aggregation/map-reduce/troubleshoot-the-reduce-function) shell 辅助方法[db.collection.mapReduce()](/aggregation/map-reduce/troubleshoot-the-reduce-function)。

## 确认输出类型

您可以测试`reduce` function 返回的 value 与`map` function 发出的 value 的类型相同。

* 定义一个`reduceFunction1` function，它接受 arguments `keyCustId`和`valuesPrices`。 `valuesPrices`是整数的 array：

  ```
  var reduceFunction1 = function(keyCustId, valuesPrices) {
      return Array.sum(valuesPrices);
  };
  ```
* 定义 sample array 整数：

  ```
  var myTestValues = [ 5, 5, 10 ];
  ```
* 使用`myTestValues`调用`reduceFunction1`：

  ```
  reduceFunction1('myKey', myTestValues);
  ```
* 验证`reduceFunction1`返回 integer：

  ```
  20
  ```
* 定义一个`reduceFunction2` function，它接受 arguments `keySKU`和`valuesCountObjects`。 `valuesCountObjects`是包含两个字段`count`和`qty`的 array 文档：

  ```
  var reduceFunction2 = function(keySKU, valuesCountObjects) {
  reducedValue = { count: 0, qty: 0 };
      for (var idx = 0; idx <; valuesCountObjects.length; idx++) {
          reducedValue.count += valuesCountObjects[idx].count;
          reducedValue.qty += valuesCountObjects[idx].qty;
      }

      return reducedValue;
  };
  ```
* 定义 sample array 文档：

  ```
  var myTestObjects = [
      { count: 1, qty: 5 },
      { count: 2, qty: 10 },
      { count: 3, qty: 15 }
  ];
  ```
* 使用`myTestObjects`调用`reduceFunction2`：

  ```
  reduceFunction2('myKey', myTestObjects);
  ```
* 验证`reduceFunction2`返回的文档中包含`count`和`qty`字段：

  ```
  { "count" : 6, "qty" : 30 }
  ```

## 确保对映射值的 Order 不敏感

`reduce` function 以`key`和`values` array 为参数。您可以测试`reduce` function 的结果不依赖于`values` array 中元素的 order。

* 定义 sample `values1` array 和 sample `values2` array，它们只在 array 元素的 order 中有所不同：

  ```
  var values1 = [
      { count: 1, qty: 5 },
      { count: 2, qty: 10 },
      { count: 3, qty: 15 }
  ];
  var values2 = [
      { count: 3, qty: 15 },
      { count: 1, qty: 5 },
      { count: 2, qty: 10 }
  ];
  ```
* 定义一个`reduceFunction2` function，它接受 arguments `keySKU`和`valuesCountObjects`。 `valuesCountObjects`是包含两个字段`count`和`qty`的 array 文档：

  ```
  var reduceFunction2 = function(keySKU, valuesCountObjects) {
  reducedValue = { count: 0, qty: 0 };
      for (var idx = 0; idx < valuesCountObjects.length; idx++) {
          reducedValue.count += valuesCountObjects[idx].count;
          reducedValue.qty += valuesCountObjects[idx].qty;
      }

      return reducedValue;
  };
  ```
* 先使用`values1`然后使用`values2`调用`reduceFunction2`：

  ```
  reduceFunction2('myKey', values1);
  reduceFunction2('myKey', values2);
  ```
* 验证`reduceFunction2`返回相同的结果：

  ```
  { "count" : 6, "qty" : 30 }
  ```

## 确保减少 Function Idempotence

因为 map-reduce 操作可能会为同一个 key 多次调用`reduce`，并且不会为工作集中的 key 的单个实例调用`reduce`，`reduce` function 必须 return 与从该值发出的 value 相同类型的 value。 `map` function。您可以测试`reduce` function process“减少”值而不影响最终的 value。

* 定义一个`reduceFunction2` function，它接受 arguments `keySKU`和`valuesCountObjects`。 `valuesCountObjects`是包含两个字段`count`和`qty`的 array 文档：

  ```
  var reduceFunction2 = function(keySKU, valuesCountObjects) {
  reducedValue = { count: 0, qty: 0 };
      for (var idx = 0; idx <; valuesCountObjects.length; idx++) {
          reducedValue.count += valuesCountObjects[idx].count;
          reducedValue.qty += valuesCountObjects[idx].qty;
      }

      return reducedValue;
  };
  ```
* 定义 sample key：

  ```
  var myKey = 'myKey';
  ```
* 定义 sample `valuesIdempotent` array，其中包含一个调用`reduceFunction2` function 的元素：

  ```
  var valuesIdempotent = [
      { count: 1, qty: 5 },
      { count: 2, qty: 10 },
      reduceFunction2(myKey, [ { count:3, qty: 15 } ] )
  ];
  ```
* 定义一个 sample `values1` array，它结合了传递给`reduceFunction2`的值：

  ```
  var values1 = [
      { count: 1, qty: 5 },
      { count: 2, qty: 10 },
      { count: 3, qty: 15 }
  ];
  ```
* 首先使用`myKey`和`valuesIdempotent`调用`reduceFunction2`，然后使用`myKey`和`values1`调用`reduceFunction2`：

  ```
  reduceFunction2(myKey, valuesIdempotent);
  reduceFunction2(myKey, values1);
  ```
* 验证`reduceFunction2`返回相同的结果：

  ```
  { "count" : 6, "qty" : 30 }
  ```

译者：李冠飞

校对：


# Map-Reduce转换到聚合管道

从4.4版本开始，MongoDB添加了`$accumulator`和`$function` aggregation运算符。这些运算符为用户提供了定义自定义聚合表达式的能力。使用这些操作，可以大致重写map-reduce表达式，如下表所示。

> **注意**
>
> 可以使用聚合管道操作符(如$group、$merge等)重写各种map-reduce表达式，而不需要自定义函数。
>
> 例如，请参见map-reduce示例。

## Map-Reduce到聚合管道转换表

这张表只是粗略的翻译。例如，该表显示了使用`$project`的`mapFunction`的近似转换。

* 然而，mapFunction逻辑可能需要额外的阶段，例如，如果逻辑包括对数组的迭代:

  ```
  function() {
     this.items.forEach(function(item){ emit(item.sku, 1); });
  }
  ```

  然后，聚合管道包括一个`$unwind`和一个`$project`:

  ```
  { $unwind: "$items "},
  { $project: { emits: { key: { "$items.sku" }, value: 1 } } },
  ```
* `$project`中的`emit`字段可以被命名为其他名称。为了进行可视化比较，选择了字段名称emit。

| Map-Reduce                                                                                                                                                                                             | Aggregation Pipeline                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| db.collection.mapReduce( \<mapFunction>, \<reduceFunction>, { query: \<queryFilter>, sort: \<sortOrder>, limit: \<number>, finalize: \<finalizeFunction>, out: \<collection> } )                       | db.collection.aggregate( \[ { $match: \<queryFilter> }, { $sort: \<sortOrder> }, { $limit: \<number> }, { $project: { emits: { k: \<expression>, v: \<expression> } } }, { $unwind: “$emits” }, { $group: { \_id: “$emits.k”}, value: { $accumulator: { init: \<initCode>, accumulate: \<reduceFunction>, accumulateArgs: \[ “$emit.v”], merge: \<reduceFunction>, finalize: \<finalizeFunction>, lang: “js” }} } }, { $out: \<collection> } ] )                                                                                                                                                                                                                             |
| db.collection.mapReduce( \<mapFunction>, \<reduceFunction>, { query: \<queryFilter>, sort: \<sortOrder>, limit: \<number>, finalize: \<finalizeFunction>, out: { merge: \<collection>, db: \<db> } } ) | db.collection.aggregate( \[ { $match: \<queryFilter> }, { $sort: \<sortOrder> }, { $limit: \<number> }, { $project: { emits: { k: \<expression>, v: \<expression> } } }, { $unwind: “$emits” }, { $group: { \_id: “$emits.k”}, value: { $accumulator: { init: \<initCode>, accumulate: \<reduceFunction>, accumulateArgs: \[ “$emit.v”], merge: \<reduceFunction>, finalize: \<finalizeFunction>, lang: “js” }} } }, { $out: { db: \<db>, coll: \<collection> } } ] )                                                                                                                                                                                                        |
| db.collection.mapReduce( \<mapFunction>, \<reduceFunction>, { query: \<queryFilter>, sort: \<sortOrder>, limit: \<number>, finalize: \<finalizeFunction>, out: { merge: \<collection>, db: \<db> } } ) | db.collection.aggregate( \[ { $match: \<queryFilter> }, { $sort: \<sortOrder> }, { $limit: \<number> }, { $project: { emits: { k: \<expression>, v: \<expression> } } }, { $unwind: “$emits” }, { $group: { \_id: “$emits.k”}, value: { $accumulator: { init: \<initCode>, accumulate: \<reduceFunction>, accumulateArgs: \[ “$emit.v”], merge: \<reduceFunction>, finalize: \<finalizeFunction>, lang: “js” }} } }, { $merge: { into: { db: \<db>, coll: \<collection>}, on: “\_id” whenMatched: “replace”, whenNotMatched: “insert” } }, ] )                                                                                                                               |
| db.collection.mapReduce( \<mapFunction>, \<reduceFunction>, { query: \<queryFilter>, sort: \<sortOrder>, limit: \<number>, finalize: \<finalizeFunction>, out: { merge: \<collection>, db: \<db> } } ) | db.collection.aggregate( \[ { $match: \<queryFilter> }, { $sort: \<sortOrder> }, { $limit: \<number> }, { $project: { emits: { k: \<expression>, v: \<expression> } } }, { $unwind: “$emits” }, { $group: { \_id: “$emits.k”}, value: { $accumulator: { init: \<initCode>, accumulate: \<reduceFunction>, accumulateArgs: \[ “$emit.v”], merge: \<reduceFunction>, finalize: \<finalizeFunction>, lang: “js” }} } }, { $merge: { into: { db: \<db>, coll: \<collection> }, on: “\_id” whenMatched: \[ { $project: { value: { $function: { body: \<reduceFunction>, args: \[ “$\_id”, \[ “$value”, “$$new\.value” ] ], lang: “js” } } } } ] whenNotMatched: “insert” } }, ] ) |
| db.collection.mapReduce( \<mapFunction>, \<reduceFunction>, { query: \<queryFilter>, sort: \<sortOrder>, limit: \<number>, finalize: \<finalizeFunction>, out: { inline: 1 } } )                       | db.collection.aggregate( \[ { $match: \<queryFilter> }, { $sort: \<sortOrder> }, { $limit: \<number> }, { $project: { emits: { k: \<expression>, v: \<expression> } } }, { $unwind: “$emits” }, { $group: { \_id: “$emits.k”}, value: { $accumulator: { init: \<initCode>, accumulate: \<reduceFunction>, accumulateArgs: \[ “$emit.v”], merge: \<reduceFunction>, finalize: \<finalizeFunction>, lang: “js” }} } } ] )                                                                                                                                                                                                                                                      |

## 例子

可以使用聚合管道操作符(如`$group`、`$merge`等)重写各种map-reduce表达式，而不需要自定义函数。但是，为了说明目的，下面的例子提供了两种选择。

### 示例1

通过`cust_id`对订单集合组执行以下`map-reduce`操作，并计算每个`cust_id`的价格总和:

```
var mapFunction1 = function() {
   emit(this.cust_id, this.price);
};

var reduceFunction1 = function(keyCustId, valuesPrices) {
   return Array.sum(valuesPrices);
};

db.orders.mapReduce(
   mapFunction1,
   reduceFunction1,
   { out: "map_reduce_example" }
)
```

\*\*备选方案1:(推荐)\*\*您可以重写操作到聚合管道，而不将map-reduce函数转换为等效的管道阶段:

```
db.orders.aggregate([
   { $group: { _id: "$cust_id", value: { $sum: "$price" } } },
   { $out: "agg_alternative_1" }
])
```

\*\*备选方案2:(仅为说明目的)\*\*下面的聚合管道提供了各种map-reduce函数的转换，使用`$accumulator`定义自定义函数:

```
db.orders.aggregate( [
   { $project: { emit: { key: "$cust_id", value: "$price" } } },  // equivalent to the map function
   { $group: {                                                    // equivalent to the reduce function
        _id: "$emit.key",
        valuesPrices: { $accumulator: {
                    init: function() { return 0; },
                    initArgs: [],
                    accumulate: function(state, value) { return state + value; },
                    accumulateArgs: [ "$emit.value" ],
                    merge: function(state1, state2) { return state1 + state2; },
                    lang: "js"
        } }
   } },
   { $out: "agg_alternative_2" }
] )
```

1. 首先，`$project`阶段输出带有emit字段的文档。emit字段是一个包含以下字段的文档:

   * `key`包含`cust_id`文档的值
   * `value`包含`price`文档的值

   ```
   { "_id" : 1, "emit" : { "key" : "Ant O. Knee", "value" : 25 } }
   { "_id" : 2, "emit" : { "key" : "Ant O. Knee", "value" : 70 } }
   { "_id" : 3, "emit" : { "key" : "Busby Bee", "value" : 50 } }
   { "_id" : 4, "emit" : { "key" : "Busby Bee", "value" : 25 } }
   { "_id" : 5, "emit" : { "key" : "Busby Bee", "value" : 50 } }
   { "_id" : 6, "emit" : { "key" : "Cam Elot", "value" : 35 } }
   { "_id" : 7, "emit" : { "key" : "Cam Elot", "value" : 25 } }
   { "_id" : 8, "emit" : { "key" : "Don Quis", "value" : 75 } }
   { "_id" : 9, "emit" : { "key" : "Don Quis", "value" : 55 } }
   { "_id" : 10, "emit" : { "key" : "Don Quis", "value" : 25 } }
   ```
2. 然后，`$group`使用`$accumulator`操作符来添加发出的值:

   ```
   { "_id" : "Don Quis", "valuesPrices" : 155 }
   { "_id" : "Cam Elot", "valuesPrices" : 60 }
   { "_id" : "Ant O. Knee", "valuesPrices" : 95 }
   { "_id" : "Busby Bee", "valuesPrices" : 125 }
   ```
3. 最后，`$out`将输出写入集合`agg_alternative_2`。或者，您可以使用`$merge`而不是`$out`。

### 示例2

以下字段对`orders`集合组的map-reduce操作，`item.sku`并计算每个sku的订单数量和总订购量。然后，该操作将为每个sku值计算每个订单的平均数量，并将结果合并到输出集合中。

```
var mapFunction2 = function() {
    for (var idx = 0; idx < this.items.length; idx++) {
       var key = this.items[idx].sku;
       var value = { count: 1, qty: this.items[idx].qty };

       emit(key, value);
    }
};

var reduceFunction2 = function(keySKU, countObjVals) {
   reducedVal = { count: 0, qty: 0 };

   for (var idx = 0; idx < countObjVals.length; idx++) {
       reducedVal.count += countObjVals[idx].count;
       reducedVal.qty += countObjVals[idx].qty;
   }

   return reducedVal;
};

var finalizeFunction2 = function (key, reducedVal) {
  reducedVal.avg = reducedVal.qty/reducedVal.count;
  return reducedVal;
};

db.orders.mapReduce(
   mapFunction2,
   reduceFunction2,
   {
     out: { merge: "map_reduce_example2" },
     query: { ord_date: { $gte: new Date("2020-03-01") } },
     finalize: finalizeFunction2
   }
 );
```

\*\*备选方案1:(推荐)\*\*您可以重写操作到聚合管道，而不将map-reduce函数转换为等效的管道阶段:

```
db.orders.aggregate( [
   { $match: { ord_date: { $gte: new Date("2020-03-01") } } },
   { $unwind: "$items" },
   { $group: { _id: "$items.sku", qty: { $sum: "$items.qty" }, orders_ids: { $addToSet: "$_id" } }  },
   { $project: { value: { count: { $size: "$orders_ids" }, qty: "$qty", avg: { $divide: [ "$qty", { $size: "$orders_ids" } ] } } } },
   { $merge: { into: "agg_alternative_3", on: "_id", whenMatched: "replace",  whenNotMatched: "insert" } }
] )
```

\*\*备选方案2:(仅为说明目的)\*\*下面的聚合管道提供了各种map-reduce函数的转换，使用`$accumulator`定义自定义函数:

```
db.orders.aggregate( [
    { $match: { ord_date: {$gte: new Date("2020-03-01") } } },
    { $unwind: "$items" },
    { $project: { emit: { key: "$items.sku", value: { count: { $literal: 1 }, qty: "$items.qty" } } } },
    { $group: {
           _id: "$emit.key",
           value: { $accumulator: {
             init: function() { return { count: 0, qty: 0 }; },
             initArgs: [],
             accumulate: function(state, value) {
                  state.count += value.count;
                  state.qty += value.qty;
                  return state;
             },
             accumulateArgs: [ "$emit.value" ],
             merge: function(state1, state2) {
                return { count: state1.count + state2.count, qty: state1.qty + state2.qty };
             },
             finalize: function(state) {
                state.avg = state.qty / state.count;
                return state;
             },
             lang: "js"}
          }
    } },
    { $merge: {
       into: "agg_alternative_4",
       on: "_id",
       whenMatched: "replace",
       whenNotMatched: "insert"
    } }
] )
```

1. `$match`阶段只选择那些ord\_date大于或等于new Date("2020-03-01")的文档。
2. `$unwinds`阶段按items数组字段分解文档，为每个数组元素输出一个文档。例如:

   ```
   { "_id" : 1, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-01T00:00:00Z"), "price" : 25, "items" : { "sku" : "oranges", "qty" : 5, "price" : 2.5 }, "status" : "A" }
   { "_id" : 1, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-01T00:00:00Z"), "price" : 25, "items" : { "sku" : "apples", "qty" : 5, "price" : 2.5 }, "status" : "A" }
   { "_id" : 2, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 70, "items" : { "sku" : "oranges", "qty" : 8, "price" : 2.5 }, "status" : "A" }
   { "_id" : 2, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 70, "items" : { "sku" : "chocolates", "qty" : 5, "price" : 10 }, "status" : "A" }
   { "_id" : 3, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 50, "items" : { "sku" : "oranges", "qty" : 10, "price" : 2.5 }, "status" : "A" }
   { "_id" : 3, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 50, "items" : { "sku" : "pears", "qty" : 10, "price" : 2.5 }, "status" : "A" }
   { "_id" : 4, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-18T00:00:00Z"), "price" : 25, "items" : { "sku" : "oranges", "qty" : 10, "price" : 2.5 }, "status" : "A" }
   { "_id" : 5, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-19T00:00:00Z"), "price" : 50, "items" : { "sku" : "chocolates", "qty" : 5, "price" : 10 }, "status" : "A" }
   ...
   ```
3. `$project`阶段输出带有emit字段的文档。emit字段是一个包含以下字段的文档:

   * `key`包含`items.sku`值
   * `value`包含具有`qty`值和`count`值的文档

   ```
   { "_id" : 1, "emit" : { "key" : "oranges", "value" : { "count" : 1, "qty" : 5 } } }
   { "_id" : 1, "emit" : { "key" : "apples", "value" : { "count" : 1, "qty" : 5 } } }
   { "_id" : 2, "emit" : { "key" : "oranges", "value" : { "count" : 1, "qty" : 8 } } }
   { "_id" : 2, "emit" : { "key" : "chocolates", "value" : { "count" : 1, "qty" : 5 } } }
   { "_id" : 3, "emit" : { "key" : "oranges", "value" : { "count" : 1, "qty" : 10 } } }
   { "_id" : 3, "emit" : { "key" : "pears", "value" : { "count" : 1, "qty" : 10 } } }
   { "_id" : 4, "emit" : { "key" : "oranges", "value" : { "count" : 1, "qty" : 10 } } }
   { "_id" : 5, "emit" : { "key" : "chocolates", "value" : { "count" : 1, "qty" : 5 } } }
   ...
   ```
4. `$group`使用`$accumulator`操作符来添加发出的计数和数量，并计算avg字段:

   ```
   { "_id" : "chocolates", "value" : { "count" : 3, "qty" : 15, "avg" : 5 } }
   { "_id" : "oranges", "value" : { "count" : 7, "qty" : 63, "avg" : 9 } }
   { "_id" : "carrots", "value" : { "count" : 2, "qty" : 15, "avg" : 7.5 } }
   { "_id" : "apples", "value" : { "count" : 4, "qty" : 35, "avg" : 8.75 } }
   { "_id" : "pears", "value" : { "count" : 1, "qty" : 10, "avg" : 10 } }
   ```
5. 最后，`$merge`将输出写入集合`agg_alternative_4`。如果现有文档具有与新结果相同的键\_id，则操作将覆盖现有文档。如果没有具有相同密钥的现有文档，操作将插入该文档。

> **也可以看看**\
> [聚合命令比较](/aggregation/map-reduce/map-reduce-to-aggregation-pipeline)

译者：李冠飞

校对：


# 聚合参考

* [聚合管道快速参考](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)

  聚合管道的快速参考卡。
* [聚合命令](/aggregation/aggregation-reference/aggregation-commands)

  数据聚合命令的引用，该命令为MongoDB的聚合功能提供接口。
* [聚合命令比较](/aggregation/aggregation-reference/aggregation-commands-commparison)

  [MapReduce](/aggregation/aggregation-reference)和[Aggregate](/aggregation/aggregation-reference)命令的比较。
* [聚合管道操作符](/can-kao/yun-suan-fu/aggregation-pipeline-operators)

  聚合管道操作有一个操作符集合，可用于在管道阶段中定义和操作文档。
* [聚合表达式中的变量](/aggregation/aggregation-reference/variables-in-aggregation-expressions)

  在聚合管道表达式中使用变量。
* [SQL 到聚合映射图表](/aggregation/aggregation-reference/sql-to-aggregation-mapping-chart)

  使用MongoDB和常见SQL语句中的聚合管道和操作符概述SQL和MongoDB中的常见聚合操作。

译者：李冠飞

校对：李冠飞


# 聚合管道快速参考

在本页面

* [阶段](#stages)
* [表达式](#expressions)
* [运算符表达式](#operator-expressions)
* [表达式运算符的索引](#index-of-expression-operators)

  > 有关特定运算符的详细信息，包括语法和示例，请单击特定的运算符以转到其参考页面。

## 阶段

### 阶段(db.collection.aggregate)

在[db.collection.aggregate](/can-kao/mongo-shell-methods/collection-methods/db-collection-aggregate)方法中，管道阶段出现在数组中。文档按顺序通过各个阶段。除[$out](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference), [$merge](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)和[$geoNear](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)阶段之外的所有阶段都可以在管道中多次出现。

```
db.collection.aggregate( [ { <stage> }, ... ] )
```

| 阶段                                                                                         | 描述                                                                                                                                                                                                                                                                                                                                                                                                                     |
| ------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [$addFields](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)      | 向文档添加新字段。类似于[$project](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)，[$addFields](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)重塑了流中的每个文档;具体而言，通过向输出文档添加新字段，该文档包含输入文档和新添加字段中的现有字段。 [`$set`](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)是[`$addFields`](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)的别名。 |
| [$bucket](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)         | 根据指定的表达式和存储区边界，将传入的文档分组，称为bucket。                                                                                                                                                                                                                                                                                                                                                                                      |
| [$bucketAuto](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)     | 根据指定的表达式将传入的文档分类为特定数量的组(称为bucket)。自动确定bucket边界，以便将文档均匀地分配到指定数量的bucket中。                                                                                                                                                                                                                                                                                                                                                |
| [$collStats](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)      | 返回有关集合或视图的统计信息。                                                                                                                                                                                                                                                                                                                                                                                                        |
| [$count](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)          | 返回聚合管道此阶段的文档数量计数。                                                                                                                                                                                                                                                                                                                                                                                                      |
| [$facet](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)          | 在同一组输入文档的单个阶段内处理多个[聚合管道](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)。允许创建能够在单个阶段中跨多个维度或方面描述数据的多面聚合。                                                                                                                                                                                                                                                                                       |
| [$geoNear](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)        | 根据与地理空间点的接近程度返回一个有序的文档流。将[$match](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)，[$sort](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)和[$limit](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)的功能合并到地理空间数据中。输出文档包括附加距离字段，并且可以包括位置标识符字段。                                                                                                 |
| [$graphLookup](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)    | 对集合执行递归搜索。对于每个输出文档，添加一个新的数组字段，该字段包含该文档的递归搜索的遍历结果。                                                                                                                                                                                                                                                                                                                                                                      |
| [$group](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)          | 按指定的标识符表达式对文档进行分组，并将累加器表达式(如果指定)应用于每个组。使用所有输入文档并为每个不同的组输出一个文档。输出文档只包含标识符字段和累积字段(如果指定的话)。                                                                                                                                                                                                                                                                                                                               |
| [$indexStats](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)     | 返回有关集合的每个索引的使用情况的统计信息。                                                                                                                                                                                                                                                                                                                                                                                                 |
| [$limit](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)          | 将未修改的前 n 个文档传递给管道，其中 n 是指定的限制。对于每个输入文档，输出一个文档(对于前 n 个文档)或零文档(在前 n 个文档之后)。                                                                                                                                                                                                                                                                                                                                              |
| [$listSessions](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)   | 列出足以传播到`system.sessions`集合的所有会话。                                                                                                                                                                                                                                                                                                                                                                                       |
| [$lookup](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)         | 对同一数据库中的另一个集合执行左外连接，从“已连接”集合中过滤文档以进行处理。                                                                                                                                                                                                                                                                                                                                                                                |
| [$match](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)          | 过滤文档流以仅允许匹配的文档未经修改地传递到下一个管道阶段。 [$match](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)使用标准的 MongoDB 查询。对于每个输入文档，输出一个文档(匹配)或零文档(不匹配)。                                                                                                                                                                                                                                                         |
| [$merge](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)          | 将聚合管道的结果文档写入集合。这个阶段可以将结果合并到一个输出集合中(插入新文档、合并文档、替换文档、保留现有文档、操作失败、使用自定义更新管道处理文档)。要使用[`$merge`](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)阶段，它必须是管道中的最后一个阶段。 version 4.2 中的新功能                                                                                                                                                                                                               |
| [$out](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)            | 将聚合管道的结果文档写入集合。要使用[$out](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)阶段，它必须是管道中的最后一个阶段。                                                                                                                                                                                                                                                                                                    |
| [$planCacheStats](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) | 返回集合的计划缓存信息。                                                                                                                                                                                                                                                                                                                                                                                                           |
| [$project](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)        | 重新整形流中的每个文档，例如添加新字段或删除现有字段。对于每个输入文档，输出一个文档。 有关删除现有字段，请参见[`$unset`](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)。                                                                                                                                                                                                                                                                           |
| [$redact](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)         | 通过基于文档本身中存储的信息限制每个文档的内容来重塑流中的每个文档。合并[$project](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)和[$match](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)的功能。可用于实现字段级修订。对于每个输入文档，输出一个或零个文档。                                                                                                                                                                            |
| [$replaceRoot](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)    | 用指定的嵌入文档替换文档。该操作将替换输入文档中的所有现有字段，包括`_id`字段。指定嵌入在输入文档中的文档，以将嵌入的文档提升到顶层。 [`$replaceWith`](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)是[`$replaceRoot`](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)阶段的别名。                                                                                                                                                        |
| [$replaceWith](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)    | 用指定的嵌入文档替换文档。该操作将替换输入文档中的所有现有字段，包括`_id`字段。指定嵌入在输入文档中的文档，以将嵌入的文档提升到顶层。 [`$replaceWith`](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)是[`$replaceRoot`](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)阶段的别名。                                                                                                                                                        |
| [$sample](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)         | 从输入中随机选择指定数量的文档。                                                                                                                                                                                                                                                                                                                                                                                                       |
| [$set](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)            | 向文档添加新字段。与[`$project`](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)类似，[`$set`](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)会重新塑造流中的每个文档；具体来说，通过向包含输入文档中的现有字段和新添加字段的输出文档添加新字段。 [`$set`](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)是[`$addFields`](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)阶段的别名。  |
| [$skip](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)           | 跳过前 n 个文档，其中 n 是指定的跳过编号，并将其余未修改的文档传递给管道。对于每个输入文档，输出零文档(对于前 n 个文档)或一个文档(如果在前 n 个文档之后)。                                                                                                                                                                                                                                                                                                                                  |
| [$sort](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)           | 按指定的排序键重新排序文档。只有顺序改变;文件保持不变。对于每个输入文档，输出一个文档。                                                                                                                                                                                                                                                                                                                                                                           |
| [$sortByCount](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)    | 根据指定表达式的值对传入文档进行分组，然后计算每个不同组中的文档计数。                                                                                                                                                                                                                                                                                                                                                                                    |
| [$unionWith](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)      | 执行两个集合的并集;例如，将来自两个集合的管道结果组合成一个结果集。 version 4.4 中的新功能                                                                                                                                                                                                                                                                                                                                                                   |
| [$unset](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)          | 从文档中移除/排除字段。 [`$unset`](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)是移除字段阶段的[`$project stage`](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)的别名。                                                                                                                                                                                                                |
| [$unwind](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)         | 解析输入文档中的数组字段，为每个元素输出一个文档。每个输出文档用一个元素值替换数组。对于每个输入文档，输出n个文档，其中n是数组元素的数量，对于空数组可以为零。                                                                                                                                                                                                                                                                                                                                       |

### 阶段(db.aggregate)

从 version 3.6 开始，MongoDB 也提供了[db.aggregate](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)方法：

```
db.aggregate( [ { <stage> }, ... ] )
```

以下阶段使用[db.aggregate()](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)方法而不是[db.collection.aggregate()](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)方法。

| 阶段                                                                                            | 描述                                                                                                                                                                                                                       |
| --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [$currentOp](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)         | 返回有关 MongoDB 部署的活动 and/or 休眠操作的信息。                                                                                                                                                                                       |
| [$listLocalSessions](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) | 列出当前连接的[mongos](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)或[mongod](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)实例上正在使用的所有活动会话。这些会话可能尚未传播到`system.sessions`集合。 |

### 阶段可用更新

从MongoDB 4.2开始，你可以使用聚合管道更新:

| 命令                                                                                       | mongo Shell 方法                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| ---------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [findAndModify](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) | [db.collection.findOneAndUpdate()](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [db.collection.findAndModify()](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)                                                                                                                                                                                                                                                                                                                                                                                      |
| [update](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)        | [db.collection.updateOne()](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [db.collection.updateMany()](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [db.collection.update()](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [Bulk.find.update()](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [Bulk.find.updateOne()](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [Bulk.find.upsert()](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) |

对于更新，管道可以包括以下阶段:

* [`$addFields`](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)及其别名[`$set`](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)
* [`$project`](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)及其别名[`$unset`](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)
* [`$replaceRoot`](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)及其别名[`$replaceWith`](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)

> **\[success] 也可以看看**
>
> [聚合管道更新](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)

## 表达式

表达式可以包括[字段路径](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)，[Literals](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)，[系统变量](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)，[表达对象](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)和[表达式操作符](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)。表达式可以嵌套。

### 字段路径

聚合表达式使用[字段路径](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)来访问输入文档中的字段。要指定字段路径，请在字段名或虚线字段名(如果字段在嵌入的文档中)前加上美元符号$。例如，“`$user`”指定用户字段的字段路径，“`$user.name`”指定“`user.name`”字段的字段路径。

`"$<field>"`等效于`"$$CURRENT.<field>"`，其中[CURRENT](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)是系统变量，默认为当前对象的根，除非在特定阶段另有说明。

### 聚合变量

MongoDB提供了在表达式中使用的各种聚合[系统变量](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)。要访问变量，请在变量名前加上`$$`。例如:

| 变量                                                                                       | 通过$$访问              | 简介/描述                                                                                                     |
| ---------------------------------------------------------------------------------------- | ------------------- | --------------------------------------------------------------------------------------------------------- |
| [NOW](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)           | **$$NOW**           | 返回当前的日期时间值，该值在部署的所有成员之间是相同的，并在整个聚合管道中保持不变。(4.2 + 版本中可用)                                                   |
| [CLUSTER\_TIME](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) | **$$CLUSTER\_TIME** | 返回当前时间戳值，该值在部署的所有成员之间是相同的，并在整个聚合管道中保持不变。仅用于复制集和分片集群。(4.2 + 版本中可用)                                         |
| [ROOT](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)          | **$$ROOT**          | 引用根文档，即：顶级文档。                                                                                             |
| [CURRENT](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)       | **$$CURRENT**       | 引用字段路径的开始，默认情况下该路径是[ROOT](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)，但可以更改。 |
| [REMOVE](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)        | **$$REMOVE**        | 允许有条件地排除字段。(3.6 + 版本中可用)                                                                                  |
| [DESCEND](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)       | **$$DESCEND**       | [`$redact`](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)表达式允许的结果之一。           |
| [PRUNE](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)         | **$$PRUNE**         | [`$redact`](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)表达式允许的结果之一。           |
| [KEEP](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)          | **$$KEEP**          | [`$redact`](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)表达式允许的结果之一。           |

有关这些变量的更详细描述，请参阅[系统变量](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)。

### Literals

Literals 可以是任何类型。但是，MongoDB将以美元符号`$`开头的字符串字面值作为字段的路径，并将表达式对象中的数值/布尔字面值作为投影标志。为了避免解析文字，可以使用[$literal](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)表达式。

### 表达式对象

表达式对象具有以下形式：

```
{ <field1>: <expression1>, ... }
```

如果表达式是数值型或 boolean 型文字，MongoDB 将 literals 视为投影标志(例如： `1`或`true`包括该字段)，仅在[$project](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)阶段有效。要避免将数值或 boolean 型文字视为投影标志，请使用[$literal](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)表达式来包装数值型或 boolean 文字型。

## 运算符表达式

在这个部分

* [算数表达式运算符](#arithmetic-expression-operators)
* [数组表达式运算符](#array-expression-operators)
* [布尔表达式运算符](#boolean-expression-operators)
* [比较表达式运算符](#comparison-expression-operators)
* [条件表达式运算符](#conditional-expression-operators)
* [自定义聚合表达式运算符](#custom-aggregation-expression-operators)
* [数据大小表达式运算符](#data-size-expression-operators)
* [日期表达式运算符](#date-expression-operators)
* [文字表达式运算符](#literal-expression-operator)
* [对象表达式运算符](#object-expression-operators)
* [集合表达式运算符](#set-expression-operators)
* [字符串表达式运算符](#string-expression-operators)
* [文本表达式运算符](#text-expression-operator)
* [角度表达式运算符](#trigonometry-expression-operators)
* [类型表达式运算符](#type-expression-operators)
* [累加器($group)](#accumulators-group)
* [累加器($project 和$addFields)](#accumulators-project-addfields)
* [变量表达式运算符](#variable-expression-operators)

运算符表达式与采用带参数的函数类似。通常，这些表达式有一个数组参数 并具有以下形式：

```
{ <operator>: [ <argument1>, <argument2> ... ] }
```

如果操作符接受单个参数，则可以省略指定参数列表的外部数组：

```
{ <operator>: <argument> }
```

如果参数是文字数组，为了避免解析歧义，必须将文字数组包装在[$literal](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)表达式中，或者保留指定参数列表的外部数组。

### 算数表达式运算符

算术表达式对数字执行数学运算。一些算术表达式也可以支持日期算术。

| 名称                                                                                                                                                                                            | 描述                                                                                                                                             |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| [$abs](/can-kao/yun-suan-fu/aggregation-pipeline-operators/abs-aggregation)                                                                                                                   | 返回数字的绝对值。                                                                                                                                      |
| [$add](/can-kao/yun-suan-fu/aggregation-pipeline-operators/add-aggregation)                                                                                                                   | 添加 numbers 以返回总和，或添加 numbers 和 date 以返回新的 date。如果添加 numbers 和 date，则将 numbers 视为毫秒。接受任意数量的参数表达式，但最多只能有一个表达式解析为 date。                           |
| [$ceil](/can-kao/yun-suan-fu/aggregation-pipeline-operators/ceil-aggregation)                                                                                                                 | 返回大于或等于指定数字的最小整数。                                                                                                                              |
| [$divide](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/divide-aggregation.md)     | 返回将第一个数除以第二个数的结果。接受两个参数表达式。                                                                                                                    |
| [$exp](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/exp-aggregation.md)           | 将 e 提高到指定的指数。                                                                                                                                  |
| [$floor](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/floor-aggregation.md)       | 返回小于或等于指定数字的最大整数。                                                                                                                              |
| [$ln](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/ln-aggregation.md)             | 计算数字的自然对数。                                                                                                                                     |
| [$log](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/log-aggregation.md)           | 计算指定基数中的数字的对数。                                                                                                                                 |
| [$log10](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/log10-aggregation.md)       | 计算以10为底的对数。                                                                                                                                    |
| [$mod](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/mod-aggregation.md)           | 返回第一个数字除以第二个数字的余数。接受两个参数表达式。                                                                                                                   |
| [$multiply](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/multiply-aggregation.md) | 将数字相乘返回乘积。接受任意数量的参数表达式。                                                                                                                        |
| [$pow](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/pow-aggregation.md)           | 将数字提高到指定的指数。                                                                                                                                   |
| [$round](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/round-aggregation.md)       | 将数字四舍五入为整数或指定的小数位。                                                                                                                             |
| [$sqrt](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/sqrt-aggregation.md)         | 计算平方根。                                                                                                                                         |
| [$subtract](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/subtract-aggregation.md) | 返回从第一个值中减去第二个值的结果。如果这两个值是数字，返回差值。如果这两个值是日期，则返回差值(以毫秒为单位)。如果这两个值是日期和一个以毫秒为单位的数字，返回结果日期。接受两个参数表达式。如果这两个值是日期和数字，请首先指定 date 参数，因为从数字中减去 date 没有意义。 |
| [$trunc](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/trunc-aggregation.md)       | 将数字截断为整数或指定的小数位。                                                                                                                               |

### 数组表达式运算符

| 名称                                                                                                                                                                                                      | 描述                                                                                                 |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
| [$arrayElemAt](/can-kao/yun-suan-fu/aggregation-pipeline-operators/arrayelemat-aggregation)                                                                                                             | 返回指定的数组索引处的元素。                                                                                     |
| [$arrayToObject](/can-kao/yun-suan-fu/aggregation-pipeline-operators/arraytoobject-aggregation)                                                                                                         | 将键值对的数组转换为文档。                                                                                      |
| [$concatArrays](/can-kao/yun-suan-fu/aggregation-pipeline-operators/concatarrays-aggregation)                                                                                                           | 连接数组以返回连接的数组。                                                                                      |
| [$filter](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/filter-aggregation.md)               | 选择 array 的子集以 return array 仅包含 match 过滤条件的元素。                                                      |
| [$first](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/first-aggregation.md)                 | 返回第一个数组元素，不同于[$first](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)累加器  |
| [$in](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/in-aggregation.md)                       | 返回一个 boolean 值，指示指定的值是否在列表中。                                                                       |
| [$indexOfArray](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/indexOfArray-aggregation.md)   | 搜索列表以查找指定值的出现并返回第一个匹配项的数组索引。如果未找到子字符串，则返回`-1`。                                                     |
| [$isArray](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/isArray-aggregation.md)             | 确定操作数是否为数组。返回 boolean 值。                                                                           |
| [$last](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/last-aggregation.md)                   | 返回最后一个数组元素，不同于[$last](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)累加器。 |
| [$map](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/map-aggregation.md)                     | 将子表达式应用于数组的每个元素，并按顺序返回结果值的数组。接受命名参数。                                                               |
| [$objectToArray](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/objectToArray-aggregation.md) | 将文档转换为表示键值对的文档的数组。                                                                                 |
| [$range](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/range-aggregation.md)                 | 根据用户定义的输入输出包含整数序列的数组。                                                                              |
| [$reduce](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/reduce-aggregation.md)               | 将表达式应用于数组中的每个元素，并将它们组合为单个值。                                                                        |
| [$reverseArray](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/reverseArray-aggregation.md)   | 返回元素顺序相反的数组。                                                                                       |
| [$size](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/size-aggregation.md)                   | 返回数组中的元素数。接受单个表达式作为参数。                                                                             |
| [$slice](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/slice-aggregation.md)                 | 返回数组的子集。                                                                                           |
| [$zip](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/zip-aggregation.md)                     | 将两个数组合并在一起。                                                                                        |

### 布尔表达式运算符

Boolean 表达式将其参数表达式计算为布尔值，并返回一个boolean值作为结果。

除了`false` 布尔值之外，Boolean 表达式的计算结果如下：`null`，`0`和`undefined`值。 Boolean 表达式将所有其他值计算为`true`，包括非零数值和数组。

| 名称                                                                                                                                                                                  | 描述                                        |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------- |
| [$and](/can-kao/yun-suan-fu/aggregation-pipeline-operators/and-aggregation)                                                                                                         | 仅当其所有表达式求值为`true`时才返回`true`。接受任意数量的参数表达式。 |
| [$not](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/not-aggregation.md) | 返回与其参数表达式相反的 boolean 值。接受单个参数表达式。         |
| [$or](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/or-aggregation.md)   | 当其表达式的值为`true`时返回`true`。接受任意数量的参数表达式。     |

### 比较表达式运算符

比较表达式返回一个布尔值，除了[$cmp](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)，它返回一个数字。

比较表达式采用两个参数表达式并对值和类型进行比较，使用[指定的 BSON 比较顺序](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)表示不同类型的值。

| 名称                                                                                                                                                                                  | 描述                                                           |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ |
| [$cmp](/can-kao/yun-suan-fu/aggregation-pipeline-operators/cmp-aggregation)                                                                                                         | 如果两个值相等则返回`0`，如果第一个 value 大于第二个值则返回`1`，如果第一个值小于第二个值，则返回`-1`。 |
| [$eq](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/eq-aggregation.md)   | 如果值相等，则返回`true`。                                             |
| [$gt](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/gt-aggregation.md)   | 如果第一个值大于第二个，则返回`true`。                                       |
| [$gte](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/gte-aggregation.md) | 如果第一个值大于或等于第二个，则返回`true`。                                    |
| [$lt](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/lt-aggregation.md)   | 如果第一个值小于第二个，则返回`true`。                                       |
| [$lte](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/lte-aggregation.md) | 如果第一个值小于或等于第二个值，则返回`true`。                                   |
| [$ne](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/ne-aggregation.md)   | 如果值不相等，则返回`true`。                                            |

### 条件表达式运算符

| 名称                                                                                                                                                                                        | 描述                                                                                          |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| [$cond](/can-kao/yun-suan-fu/aggregation-pipeline-operators/cond-aggregation)                                                                                                             | 对一个表达式求值的三元运算符，并根据结果返回另外两个表达式之一的值。接受有序列表中的三个表达式或三个命名参数。                                     |
| [$ifNull](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/ifNull-aggregation.md) | 返回第一个表达式的非空结果，如果第一个表达式的结果为空，则返回第二个表达式的结果。Null结果包含未定义值或缺少字段的实例。接受两个表达式作为参数。第二个表达式的结果可以为null。 |
| [$switch](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/switch-aggregation.md) | 计算一系列用例表达。当它找到一个计算结果为`true`的表达式时，`$switch`执行一个指定的表达式并跳出控制流。                                 |

### 自定义聚合表达式运算符

| 名称                                                                                                                                                                                                  | 描述                           |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- |
| [$accumulator](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/accumulator-aggregation.md) | 定义一个自定义累加器函数 version 4.4 新功能 |
| [$function](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/function-aggregation.md)       | 定义一个自定义函数 version 4.4 新功能    |

### 数据大小表达式运算符

以下运算符返回数据元素的大小:

| 名称                                                                                                                                                                                                | 描述                                  |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------- |
| [$binarySize](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/binarySize-aggregation.md) | 返回给定字符串或二进制数据值内容的字节大小。              |
| [$bsonSize](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/bsonSize-aggregation.md)     | 返回编码为BSON的给定文档(例如：bsontype对象)的字节大小。 |

### 日期表达式运算符

以下操作符返回 date 对象或 date 对象的组件：

| 名称                                                                                                                                                                                                    | 描述                                                                        |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| [$dateFromParts](/can-kao/yun-suan-fu/aggregation-pipeline-operators/datefromparts-aggregation)                                                                                                       | 给出日期的组成部分，构造一个 BSON Date 对象。                                              |
| [$dateFromString](/can-kao/yun-suan-fu/aggregation-pipeline-operators/datefromstring-aggregation)                                                                                                     | 将 date/time 字符串转换为 date 对象。                                               |
| [$dateToParts](/can-kao/yun-suan-fu/aggregation-pipeline-operators/datetoparts-aggregation)                                                                                                           | 返回包含日期组成部分的文档。                                                            |
| [$dateToString](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/dateToString-aggregation.md) | 将 date 作为格式化的字符串返回。                                                       |
| [$dayOfMonth](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/dayOfMonth-aggregation.md)     | 将 date 的月中某天返回为 1 到 31 之间的数字。                                             |
| [$dayOfWeek](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/dayOfWeek-aggregation.md)       | 将 date 的星期几返回为 1(星期日)和 7(星期六)之间的数字。                                       |
| [$dayOfYear](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/dayOfYear-aggregation.md)       | 将 date 的年中日期作为 1 到 366(闰年)之间的数字返回。                                        |
| [$hour](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/hour-aggregation.md)                 | 将 date 的小时数作为 0 到 23 之间的数字返回。                                             |
| [$isoDayOfWeek](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/hour-aggregation.md)         | 返回 ISO 8601 格式的工作日编号，范围从`1`(星期一)到`7`(星期日)。                                |
| [$isoWeek](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/isoWeek-aggregation.md)           | 返回 ISO 8601 格式的周数，范围从`1`到`53`。 Week numbers 从`1`开始，周(星期一到星期日)包含年份的第一个星期四。 |
| [$isoWeekYear](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/isoWeekYear-aggregation.md)   | 以 ISO 8601 格式返回年份编号。年份从第 1 周的星期一(ISO 8601)开始，结束于上周的星期日(ISO 8601)。         |
| [$millisecond](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/millisecond-aggregation.md)   | 返回 date 的毫秒数，作为 0 到 999 之间的数字。                                            |
| [$minute](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/minute-aggregation.md)             | 将 date 的分钟作为 0 到 59 之间的数字返回。                                              |
| [$month](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/month-aggregation.md)               | 将 date 的月份返回为 1(1 月)和 12(12 月)之间的数字。                                      |
| [$second](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/second-aggregation.md)             | 返回 date 的秒数，作为 0 到 60 之间的数字(闰秒)。                                          |
| [$toDate](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/toDate-aggregation.md)             | 将值转换为日期。 version 4.0 中的新功能。                                               |
| [$week](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/week-aggregation.md)                 | 返回日期的周数，该数字介于0(一年的第一个星期日之前的部分周)和53(闰年)之间。                                 |
| [$year](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/year-aggregation.md)                 | 将日期的年份作为数字返回(例： 2014)。                                                    |

以下算术运算符可以使用日期操作数：

| 名称                                                                                                                                                                                            | 描述                                                                                                                      |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| [$add](/can-kao/yun-suan-fu/aggregation-pipeline-operators/add-aggregation)                                                                                                                   | 添加数字和日期以返回新的日期。如果添加数字和日期，则将这些数字视为毫秒。接受任意数量的参数表达式，但一个表达式最多只能解析一个日期。                                                      |
| [$subtract](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/subtract-aggregation.md) | 返回从第一个值减去第二个值的结果。如果这两个值是日期，则返回差值(以毫秒为单位)。如果这两个值是日期和一个以毫秒为单位的数字，则返回结果日期。接受两个参数表达式。如果这两个值是日期和数字，请首先指定日期参数，因为从数字中减去日期没有意义。 |

### 文字表达式运算符

| 名称                                                                                  | 描述                                                                                                                                                 |
| ----------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| [$literal](/can-kao/yun-suan-fu/aggregation-pipeline-operators/literal-aggregation) | 返回一个不需要解析的值。用于聚合管道可解释为表达式的值。例如，将[$literal](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)表达式用于以`$`开头的 string，以避免解析为字段路径。 |

### 对象表达式运算符

| 名称                                                                                                                                                                                                      | 描述                                    |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- |
| [$mergeObjects](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/mergeObjects-aggregation.md)   | 将多个文档合并为一个文档。 version 3.6 中的新内容。      |
| [$objectToArray](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/objectToArray-aggregation.md) | 将文档转换为表示键值对的文档的数组。 version 3.6 中的新内容。 |

### 集合表达式运算符

Set 表达式对数组执行 set 操作，将数组视为集合。 Set 表达式忽略每个输入数组中的重复条目和元素的顺序。

如果 set 操作返回一个集合，则该操作会过滤掉结果中的重复项，以输出仅包含唯一条目的数组。输出数组中元素的顺序未指定。

如果集合包含嵌套的数组元素，则 set 表达式不会深入到嵌套的数组中，而是在最外层处计算数组。

| 名称                                                                                                                                                                                                          | 描述                                                                                                                                            |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| [$allElementsTrue](/can-kao/yun-suan-fu/aggregation-pipeline-operators/allelementstrue-aggregation)                                                                                                         | 如果没有集合的元素计算为`false`，则返回`true`，否则返回`false`。接受单个参数表达式。                                                                                          |
| [$anyElementTrue](/can-kao/yun-suan-fu/aggregation-pipeline-operators/anyelementtrue-aggregation)                                                                                                           | 如果集合中的任意一个元素求值为`true`，则返回`true`；否则，返回`false`。接受单个参数表达式。                                                                                       |
| [$setDifference](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/setDifference-aggregation.md)     | 返回一个集合，其中的元素出现在第一个集合中但不出现在第二个集合中；即：执行第二个集合相对于第一个集合的[相对补充](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)。接受两个参数表达式。 |
| [$setEquals](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/setEquals-aggregation.md)             | 如果输入 sets 具有相同的不同元素，则返回`true`。接受两个或多个参数表达式。                                                                                                   |
| [$setIntersection](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/setIntersection-aggregation.md) | 返回一个包含所有输入 sets 中出现的元素的集合。接受任意数量的参数表达式。                                                                                                       |
| [$setIsSubset](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/setIsSubset-aggregation.md)         | 如果第一组的所有元素出现在第二组中，包括第一个集合和第二个集合相等时，则返回`true`；即：不是[严格的子集](http://en.wikipedia.org/wiki/Subset)。接受两个参数表达式。                                      |
| [$setUnion](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Reference/Operators/Aggregation-Pipeline-Operators/setUnion-aggregation.md)               | 返回包含出现在任何输入集合中的元素的集合。                                                                                                                         |

### 字符串表达式运算符

除了[$concat](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)之外，字符串表达式只对ASCII字符的字符串具有定义良好的行为。

无论使用哪个字符，[$concat](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)行为都是定义良好的。

| 名称                                                                                         | 描述                                                                                                                                                                                  |
| ------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [$concat](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)         | 连接任意数量的 strings。                                                                                                                                                                    |
| [$dateFromString](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) | 将 date/time string 转换为 date object。                                                                                                                                                 |
| [$dateToString](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)   | 将 date 作为格式化的 string 返回。                                                                                                                                                            |
| [$indexOfBytes](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)   | 搜索 string 以查找子字符串的出现并返回第一次出现的 UTF-8 字节索引。如果未找到子字符串，则返回`-1`。                                                                                                                         |
| [$indexOfCP](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)      | 搜索 string 以查找子字符串的出现并返回第一次出现的 UTF-8 code 点索引。如果找不到子字符串，则返回`-1`                                                                                                                      |
| [$split](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)          | 根据分隔符将 string 拆分为子字符串。返回子字符串的 array。如果在 string 中找不到分隔符，则返回包含原始 string 的 array。                                                                                                      |
| [$strLenBytes](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)    | 返回 string 中 UTF-8 编码字节的数量。                                                                                                                                                          |
| [$strLenCP](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)       | 返回 string 中 UTF-8 [code 点](http://www.unicode.org/glossary/#exp._S_strLenBytes)的数量。                                                                                                 |
| [$strcasecmp](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)     | 执行 case-insensitive string 比较并返回：如果两个 strings 相等则返回`0`，如果第一个 string 大于第二个，则返回`1`，如果第一个 string 小于第二个，则返回`-1`。                                                                        |
| [$substr](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)         | 已过时。使用[$substrBytes](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)或[$substrCP](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)。 |
| [$substrBytes](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)    | 返回 string 的子字符串。从 string 中指定的 UTF-8 字节索引(zero-based)处的字符开始，并继续指定的字节数。                                                                                                               |
| [$substrCP](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)       | 返回 string 的子字符串。从 string 中指定的 UTF-8 [code point(CP)](http://www.unicode.org/glossary/#exp._S_substrBytes)索引(zero-based)处的字符开始，并继续指定的 code 点数。                                       |
| [$toLower](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)        | 将 string 转换为小写。接受单个参数表达式。                                                                                                                                                           |
| [$toUpper](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)        | 将 string 转换为大写。接受单个参数表达式。                                                                                                                                                           |

### 文本表达式运算符

| 名称                                                                               | 描述         |
| -------------------------------------------------------------------------------- | ---------- |
| [$meta](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) | 访问文本搜索元数据。 |

### 角度表达式运算符

| 名称                                                                               | 描述                |
| -------------------------------------------------------------------------------- | ----------------- |
| [$type](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) | 返回该字段的 BSON 数据类型。 |

\[]\(s

### 累加器($group)

可以在[$group](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)阶段使用，累加器是 operators，它们在文档通过管道时保持其 state(例： 总计，最大值，最小值和相关数据)。

当在[$group](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)阶段用作累加器时，这些 operators 将单个表达式作为输入，为每个输入文档计算一次表达式，并为共享相同 group key 的 group 文档保持其阶段。

| 名称                                                                                       | 描述                                                        |
| ---------------------------------------------------------------------------------------- | --------------------------------------------------------- |
| [$addToSet](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)     | 返回每个 group 的唯一表达式值的 array。 \_Oray 元素的 Order 是未定义的。        |
| [$avg](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)          | 返回数值的平均值。忽略 non-numeric 值。                                |
| [$first](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)        | 从每个 group 的第一个文档返回一个 value。仅当文档位于已定义的 order 中时才定义 Order。  |
| [$last](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)         | 从每个 group 的最后一个文档返回一个 value。仅当文档位于已定义的 order 中时才定义 Order。 |
| [$max](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)          | 返回每个 group 的最高表达式 value。                                  |
| [$mergeObjects](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) | 返回通过组合每个 group 的输入文档创建的文档。                                |
| [$min](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)          | 返回每个 group 的最低表达式 value。                                  |
| [$push](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)         | 返回每个 group 的表达式值的 array。                                  |
| [$stdDevPop](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)    | 返回输入值的总体标准偏差。                                             |
| [$stdDevSamp](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)   | 返回输入值的 sample 标准偏差。                                       |
| [$sum](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)          | 返回数值的总和。忽略 non-numeric 值。                                 |

### 累加器($project 和$addFields)

一些可用作[$group](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)阶段累加器的运算符也可用于[$project](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)和[$addFields](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)阶段，但不能用作累加器。在[$project](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)和[$addFields](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)阶段使用时，这些 operators 不会维护它们的 state，并且可以将单个参数或多个 arguments 作为输入。

更改了 version 3.2.

以下累加器 operators 也可用于[$project](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)和[$addFields](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)阶段。

| 名称                                                                                     | 描述                                       |
| -------------------------------------------------------------------------------------- | ---------------------------------------- |
| [$avg](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)        | 返回每个文档的指定表达式或表达式列表的平均值。忽略 non-numeric 值。 |
| [$max](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)        | 返回每个文档的指定表达式或表达式列表的最大值                   |
| [$min](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)        | 返回每个文档的指定表达式或表达式列表的最小值                   |
| [$stdDevPop](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)  | 返回输入值的总体标准偏差。                            |
| [$stdDevSamp](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) | 返回输入值的 sample 标准偏差。                      |
| [$sum](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference)        | 返回数值的总和。忽略 non-numeric 值。                |

### 变量表达式运算符

| 名称                                                                              | 描述                                               |
| ------------------------------------------------------------------------------- | ------------------------------------------------ |
| [$let](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) | 定义在子表达式范围内使用的变量，并返回子表达式的结果。接受命名参数。 接受任意数量的参数表达式。 |

## 表达式运算符的索引

|                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [$abs](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$add](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$addToSet](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$allElementsTrue](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$and](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$anyElementTrue](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$arrayElemAt](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$arrayToObject](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$avg](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$cmp](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$concat](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$concatArrays](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$cond](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$dateFromParts](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$dateToParts](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$dateFromString](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$dateToString](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) | [$dayOfMonth](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$dayOfWeek](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$dayOfYear](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$divide](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$eq](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$exp](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$filter](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$first](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$floor](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$gt](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$gte](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$hour](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$ifNull](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$in](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$indexOfArray](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$indexOfBytes](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$indexOfCP](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$isArray](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) | [$isoDayOfWeek](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$isoWeek](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$isoWeekYear](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$last](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$let](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$literal](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$ln](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$log](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$log10](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$lt](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$lte](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$map](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$max](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$mergeObjects](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$meta](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$min](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$millisecond](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) | [$minute](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$mod](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$month](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$multiply](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$ne](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$not](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$objectToArray](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$or](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$pow](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$push](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$range](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$reduce](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$reverseArray](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$second](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$setDifference](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$setEquals](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$setIntersection](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$setIsSubset](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$setUnion](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$size](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) | [$slice](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$split](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$sqrt](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$stdDevPop](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$stdDevSamp](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$strcasecmp](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$strLenBytes](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$strLenCP](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$substr](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$substrBytes](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$substrCP](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$subtract](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$sum](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$switch](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$toLower](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$toUpper](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$trunc](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$type](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$week](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$year](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) [$zip](/aggregation/aggregation-reference/aggregation-pipeline-quick-reference) |

译者：李冠飞

校对：


# 聚合命令

在本页面

* [聚合命令](#id1)
* [聚合方法](#aggregation-methods)

  > **\[success] 注意**
  >
  > 有关特定运算符的详细信息，包括语法和示例，请单击特定的运算符以转到其参考页面。

## 聚合命令

| 名称                                                                   | 描述                                               |
| -------------------------------------------------------------------- | ------------------------------------------------ |
| [aggregate](/aggregation/aggregation-reference/aggregation-commands) | 使用聚合框架执行聚合任务，例如 group。                           |
| [count](/aggregation/aggregation-reference/aggregation-commands)     | 计算集合或视图中的文档数。                                    |
| [distinct](/aggregation/aggregation-reference/aggregation-commands)  | 显示在集合或视图中为指定 key 找到的不同值。                         |
| [mapReduce](/aggregation/aggregation-reference/aggregation-commands) | 对大型数据集执行[map-reduce](/aggregation/map-reduce)聚合。 |

## 聚合方法

| 名称                                                                                                                                                                                                                  | 描述                                               |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ |
| [db.collection.aggregate()](/can-kao/mongo-shell-methods/collection-methods/db-collection-aggregate)                                                                                                                | 提供对[聚合管道](/aggregation/aggregation-pipeline)的访问。 |
| [db.collection.mapReduce()](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/docs/Reference/mongo-Shell-Methods/Collection-Methods/db-collection-mapReduce.md) | 对大型数据集执行[map-reduce](/aggregation/map-reduce)聚合。 |

译者：李冠飞

校对：李冠飞


# 聚合命令对比

在本页面

* [聚合命令比较表](#aggregation-commands-comparison-table)

> **\[success] 建议**
>
> 从4.4版开始，MongoDB添加[`$accumulator`](/aggregation/aggregation-reference/aggregation-commands-commparison)和 [`$function`](/aggregation/aggregation-reference/aggregation-commands-commparison)运算符。使用 [`$accumulator`](/aggregation/aggregation-reference/aggregation-commands-commparison)和[`$function`](/aggregation/aggregation-reference/aggregation-commands-commparison)， [`mapReduce`](/aggregation/aggregation-reference/aggregation-commands-commparison)可以使用聚合运算符重写表达式。
>
> 即使是4.4版本之前，一些map-reduce表达式也可以使用改写[其他聚合管道运算符](/aggregation/aggregation-reference/aggregation-commands-commparison)，如[`$group`](/aggregation/aggregation-reference/aggregation-commands-commparison)， [`$merge`](/aggregation/aggregation-reference/aggregation-commands-commparison)等。

## 聚合命令比较表

以下表格简要概述了 MongoDB 聚合命令的特点。

|          |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |                                                                                                                                                                                                                         |
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|          | [Aggregate](/aggregation/aggregation-reference/aggregation-commands-commparison) / [db.collection.aggregate()](/aggregation/aggregation-reference/aggregation-commands-commparison)                                                                                                                                                                                                                                                                                                                                                                                                                                                                          | [MapReduce](/aggregation/aggregation-reference/aggregation-commands-commparison) / [db.collection.mapReduce()](/aggregation/aggregation-reference/aggregation-commands-commparison)                                     |
| **描述**   | 旨在提高聚合任务的性能和可用性的具体目标。 使用“管道”方法，其中 objects 在通过一系列管道操作符(如[$group](/aggregation/aggregation-reference/aggregation-commands-commparison)，[$match](/aggregation/aggregation-reference/aggregation-commands-commparison)和[$sort](/aggregation/aggregation-reference/aggregation-commands-commparison))时进行转换。 有关管道运算符的更多信息，请参见[聚合管道操作符](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/docs/Reference/Operators/Aggregation-Pipline-Operators.md)。                                                                                                                                                           | 实现 Map-Reduce 聚合以处理大型数据集。                                                                                                                                                                                               |
| **主要特点** | 可以根据需要重复管道操作符。 管道运算符不需要为每个输入文档生成一个输出文档。 还可以生成新文档或过滤掉文档。 通过在版本4.2中添加`$merge`，可以创建按需的物化视图，在该视图中可以逐步运行管道来更新输出集合的内容。`$merge`可以将结果(插入新文档、合并文档、替换文档、保留现有文档、使操作失败、使用自定义更新管道处理文档)合并到现有集合中。                                                                                                                                                                                                                                                                                                                                                                                                                                                                           | 除了分组操作之外，还可以执行复杂的聚合任务以及对不断增长的数据集执行增量聚合。 见[Map-Reduce 例子](/aggregation/aggregation-reference/aggregation-commands-commparison)和[执行增量 Map-Reduce](/aggregation/aggregation-reference/aggregation-commands-commparison)。   |
| **灵活性**  | 从4.4版开始，可以使用[`$accumulator`](/aggregation/aggregation-reference/aggregation-commands-commparison)和[`$function`](/aggregation/aggregation-reference/aggregation-commands-commparison)定义自定义聚合表达式。 在以前的版本中，只能使用聚合管道支持的运算符和表达式。 但是，可以使用[`$project`](/aggregation/aggregation-reference/aggregation-commands-commparison) 管道运算符添加计算字段，创建新的虚拟子对象以及将子字段提取到结果的顶层。 有关更多信息，请参阅[`$project`](/aggregation/aggregation-reference/aggregation-commands-commparison)以及[聚合管道操作符](/aggregation/aggregation-reference/aggregation-commands-commparison)，以了解有关所有可用管道操作符的更多信息。                                                                                                   | 自定义`map`，`reduce`和`finalize JavaScript` 函数为聚合逻辑提供了灵活性。 有关功能的详细信息和限制，请参阅[MapReduce](/aggregation/aggregation-reference/aggregation-commands-commparison)。                                                                |
| **输出结果** | 以游标的形式返回结果。如果管道包含[`$out`](/aggregation/aggregation-reference/aggregation-commands-commparison)阶段或[`$merge`](/aggregation/aggregation-reference/aggregation-commands-commparison)阶段，则游标为空。 使用[`$out`](/aggregation/aggregation-reference/aggregation-commands-commparison)，您可以完全替换现有的输出集合或输出到新的集合。详情见[`$out`](/aggregation/aggregation-reference/aggregation-commands-commparison)。 使用[`$merge`](/aggregation/aggregation-reference/aggregation-commands-commparison)，您可以输出到新的或现有的集合。对于现有的cllections，可以指定如何将结果合并到输出集合中(插入新文档、合并文档、替换文档、保留现有文档、使操作失败、使用自定义更新管道处理文档)。有关详细信息，请参见[`$merge`](/aggregation/aggregation-reference/aggregation-commands-commparison)。 | 返回各种选项的结果(内联，新集合，合并，替换，减少)。有关输出选项的详细信息，请参阅[MapReduce](/aggregation/aggregation-reference/aggregation-commands-commparison)。                                                                                             |
| **分片**   | 支持非分片和分片输入集合。 [`$merge`](/aggregation/aggregation-reference/aggregation-commands-commparison)可以输出到非分片或分片集合。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | 支持非分片和分片输入集合。                                                                                                                                                                                                           |
| **更多信息** | [聚合管道](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Pipline.md) [db.collection.aggregate()](/aggregation/aggregation-reference/aggregation-commands-commparison) [aggregate](/aggregation/aggregation-reference/aggregation-commands-commparison)                                                                                                                                                                                                                                                                                                                           | [Map-Reduce](/aggregation/map-reduce) [db.collection.mapReduce()](/aggregation/aggregation-reference/aggregation-commands-commparison) [mapReduce](/aggregation/aggregation-reference/aggregation-commands-commparison) |

也可以看看

* [Map-Reduce to Aggregate](/aggregation/aggregation-reference/aggregation-commands-commparison)

译者：李冠飞

校对：李冠飞


# 聚合表达式中的变量

在本页面

* [用户变量](#user-variables)
* [系统变量](#system-variables)

[聚合表达式](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Reference/meta-aggregation-quick-reference.html#aggregation-expressions)可以同时使用 user-defined 和系统变量。

变量可以容纳任何[BSON 类型数据](https://github.com/mongodb-china/MongoDB-CN-Manual/tree/8490376c81d56eff95abbaddc6ee414b1e1c9705/docs/Aggregation/Aggregation-Reference/reference-bson-types.html)。要访问变量的 value，请使用带有前缀为 double 美元符号(`$$`)的变量 name 的 string。

如果变量 references 一个 object，要访问 object 中的特定字段，请使用点表示法; 即： `"$$<variable>.<field>"`。

## 用户变量

用户变量名称可以包含 ascii 字符`[_a-zA-Z0-9]`和任何 non-ascii 字符。

用户变量名必须以小写的 ascii 字母`[a-z]`或 non-ascii 字符开头。

## 系统变量

MongoDB 提供以下系统变量：

| 变量        | 描述                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ROOT`    | References 根文档，即： top-level 文档，当前正在聚合管道阶段中处理。                                                                                                                                                                                                                                                                                                                                                                                                           |
| `CURRENT` | Reference 聚合管道阶段中正在处理的字段路径的开始。除非另有说明，否则所有阶段都以[CURRENT](/aggregation/aggregation-reference/variables-in-aggregation-expressions)开头，与[ROOT](/aggregation/aggregation-reference/variables-in-aggregation-expressions)相同。 [CURRENT](/aggregation/aggregation-reference/variables-in-aggregation-expressions)可以修改。但是，由于`$<field>`等同于`$$CURRENT.<field>`，因此重新绑定[CURRENT](/aggregation/aggregation-reference/variables-in-aggregation-expressions)会改变`$`访问的含义。 |
| `REMOVE`  | 一个变量，用于计算缺少的 value。允许条件排除字段。在`$projection`中，从输出中排除设置为变量[REMOVE](/aggregation/aggregation-reference/variables-in-aggregation-expressions)的字段。 有关其用法的示例，请参阅[有条件地排除字段](/aggregation/aggregation-reference/variables-in-aggregation-expressions)。 version 3.6 中的新内容。                                                                                                                                                                                        |
| `DESCEND` | [$redact](/aggregation/aggregation-reference/variables-in-aggregation-expressions)表达式的允许结果之一。                                                                                                                                                                                                                                                                                                                                                           |
| `PRUNE`   | [$redact](/aggregation/aggregation-reference/variables-in-aggregation-expressions)表达式的允许结果之一。                                                                                                                                                                                                                                                                                                                                                           |
| `KEEP`    | [$redact](/aggregation/aggregation-reference/variables-in-aggregation-expressions)表达式的允许结果之一。                                                                                                                                                                                                                                                                                                                                                           |

> **也可以看看**
>
> [$let](/aggregation/aggregation-reference/variables-in-aggregation-expressions)，[$redact](/aggregation/aggregation-reference/variables-in-aggregation-expressions)，[$map](/aggregation/aggregation-reference/variables-in-aggregation-expressions)

译者：李冠飞

校对：




---

[Next Page](/llms-full.txt/1)

