对于 AI 代理:可在 https://www.mongodb.com/zh-cn/docs/llms.txt 获取文档索引—通过在任何 URL 路径后添加 .md 可获取所有页面的 Markdown 版本。

聚合操作

在本指南中,您可以学习;了解如何使用MongoDB PHP库执行聚合操作。

聚合操作处理 MongoDB 集合中的数据并返回计算结果。 MongoDB 聚合框架是 Query API 的一部分,以数据处理管道的概念为模型。 文档进入包含一个或多个阶段的管道,该管道将文档转换为聚合结果。

提示

完成聚合教程

您可以在服务器手册的完整聚合管道教程部分找到详细解释常见聚合任务的教程。选择一个教程,然后从页面右上角的 Select your language 下拉菜单中选择 PHP。

聚合操作类似于汽车工厂。汽车工厂有一条装配线,其中包含配备专用工具的装配站,用于完成特定的工作,例如钻机和焊机。毛坯零件会进入工厂,然后装配线将其转换并组装为成品。

聚合管道是装配线,聚合阶段是装配站,操作符表达式则是专用工具。

您可以使用查找操作执行以下动作:

  • 选择要返回的文档

  • 选择要返回的字段

  • 对结果进行排序

您可以使用聚合操作执行以下动作:

  • 运行查找操作

  • 重命名字段

  • 计算字段

  • 汇总数据

  • 对值进行分组

执行聚合操作时要考虑以下限制:

  • 返回的文档不能违反16 MB 的BSON文档大小限制。

  • 默认,管道阶段的内存限制为100 MB。 您可以创建一个选项大量,将allowDiskUse选项设置为true ,然后将该大量传递给MongoDB\Collection::aggregate()方法,从而超过此限制。

    重要

    $graphLookup 异常

    $graphLookup阶段有100 MB 的严格内存限制,并忽略allowDiskUse选项。

PHP库提供以下 API 来创建聚合管道:

  • 数组API:通过传递指定聚合阶段的数组来创建聚合管道。

  • 聚合构建器:使用工厂方法创建聚合管道,提高应用程序的类型安全性和可调试性。

以下部分介绍了每个API ,并提供了创建聚合管道的示例。

要执行聚合,请将包含管道阶段的大量作为BSON文档传递给 MongoDB\Collection::aggregate() 方法,如以下代码所示:

$pipeline = [ ['<stage>' => <parameters>], ['<stage>' => <parameters>], ...]; $cursor = $collection->aggregate($pipeline);

The examples in this section use the restaurants collection in the sample_restaurants database from the Atlas sample datasets. To learn how to create a free MongoDB deployment and load the sample datasets, see the MongoDB Get Started guide.

以下代码示例计算纽约每个区的面包店数量。 为此,它使用包含以下阶段的聚合管道:

  1. $match阶段,用于过滤cuisine字段包含值'Bakery'的文档

  2. $ 群组阶段按borough字段对匹配文档进行群组,并累积每个不同值的文档计数

$pipeline = [ ['$match' => ['cuisine' => 'Bakery']], ['$group' => ['_id' => '$borough', 'count' => ['$sum' => 1]]],]; $cursor = $collection->aggregate($pipeline); foreach ($cursor as $doc) { echo json_encode($doc), PHP_EOL;}

要查看有关MongoDB如何执行您的操作的信息,您可以指示MongoDB查询规划器对其进行解释。 MongoDB解释操作时,会返回执行计划和性能统计信息。 执行计划是MongoDB完成操作的一种潜在方式。 当您指示MongoDB解释一个操作时,它会返回MongoDB执行的计划和任何被拒绝的执行计划。

要解释聚合操作,请构造一个MongoDB\Operation\Aggregate对象并将数据库阶段、集合阶段和管道阶段作为参数传递。 然后,将MongoDB\Operation\Aggregate对象传递给MongoDB\Collection::explain()方法。

以下示例指示MongoDB解释上一节中的聚合操作:

$pipeline = [ ['$match' => ['cuisine' => 'Bakery']], ['$group' => ['_id' => '$borough', 'count' => ['$sum' => 1]]],]; $aggregate = new MongoDB\Operation\Aggregate( $collection->getDatabaseName(), $collection->getCollectionName(), $pipeline,); $result = $collection->explain($aggregate);echo json_encode($result), PHP_EOL;

要使用聚合构建器创建聚合管道,请执行以下操作:

  1. 创建一个大量来存储管道阶段。

  2. 对于每个阶段,从 Stage 中调用与所需聚合阶段同名的工厂方法。示例,要创建 $unwind 阶段,请调用 Stage::unwind() 方法。

  3. 在 Stage 方法的主体中,使用其他构建器类(例如 Query、Expression 或 Accumulator)中的方法来Express您的聚合规范。

以下代码演示了用于构建聚合管道的模板:

$pipeline = [ Stage::<factory method>( <stage specification> ), Stage::<factory method>( <stage specification> ), ...]; $cursor = $collection->aggregate($pipeline);

重要

输入验证

构建器类将值传递给根本的MongoDB操作。根据设计,构建者不是安全清理层。在将应用程序中不受信任的输入传递给构建器之前,请对其进行验证和清理。

本节中的示例改编自MongoDB Server手册。每个示例都提供了示例数据的链接,您可以将其插入数据库以测试聚合操作。

提示

与构建者合作

您可以使用构建者来支持非聚合操作,例如查找和更新操作。要学习;了解更多信息,请参阅《Operations with Builders》指南。

此示例使用服务器手册中 $group 阶段参考的 计算计数、总和和平均值 部分中给出的示例数据。

以下代码示例计算 2014 年每一天的总销售额、平均销售数量和销售计数。为此,它使用包含以下阶段的聚合管道:

  1. $match 阶段,用于过滤包含 date字段且年份为 2014 的文档

  2. $群组阶段,按日期对文档进行群组,并计算群组的总销售额、平均销售数量和销售计数

  3. $sort 阶段,用于按群组的总销售额降序对结果进行排序

$pipeline = [ MongoDB\Builder\Stage::match( date: [ MongoDB\Builder\Query::gte(new MongoDB\BSON\UTCDateTime(new DateTimeImmutable('2014-01-01'))), MongoDB\Builder\Query::lt(new MongoDB\BSON\UTCDateTime(new DateTimeImmutable('2015-01-01'))), ], ), MongoDB\Builder\Stage::group( _id: MongoDB\Builder\Expression::dateToString(MongoDB\Builder\Expression::dateFieldPath('date'), '%Y-%m-%d'), totalSaleAmount: MongoDB\Builder\Accumulator::sum( MongoDB\Builder\Expression::multiply( MongoDB\Builder\Expression::numberFieldPath('price'), MongoDB\Builder\Expression::numberFieldPath('quantity'), ), ), averageQuantity: MongoDB\Builder\Accumulator::avg( MongoDB\Builder\Expression::numberFieldPath('quantity'), ), count: MongoDB\Builder\Accumulator::sum(1), ), MongoDB\Builder\Stage::sort( totalSaleAmount: MongoDB\Builder\Type\Sort::Desc, ),]; $cursor = $collection->aggregate($pipeline); foreach ($cursor as $doc) { echo json_encode($doc), PHP_EOL;}

此示例使用服务器手册中 $unwind 阶段参考的 展开嵌入式数组 部分中给出的示例数据。

以下代码示例按标签对售出的商品进行分组,并计算每个标签的总销售额。为此,它使用包含以下阶段的聚合管道:

  1. $unwind 阶段,为 大量中的每个元素输出单独的文档items

  2. $unwind 阶段为 items.tags 数组中的每个元素输出单独的文档

  3. $ 群组阶段,按标签值对文档群组,并计算具有每个标签的商品的总销售额

$pipeline = [ MongoDB\Builder\Stage::unwind(MongoDB\Builder\Expression::arrayFieldPath('items')), MongoDB\Builder\Stage::unwind(MongoDB\Builder\Expression::arrayFieldPath('items.tags')), MongoDB\Builder\Stage::group( _id: MongoDB\Builder\Expression::fieldPath('items.tags'), totalSalesAmount: MongoDB\Builder\Accumulator::sum( MongoDB\Builder\Expression::multiply( MongoDB\Builder\Expression::numberFieldPath('items.price'), MongoDB\Builder\Expression::numberFieldPath('items.quantity'), ), ), ),]; $cursor = $collection->aggregate($pipeline); foreach ($cursor as $doc) { echo json_encode($doc), PHP_EOL;}

此示例使用服务器手册中 $lookup 阶段引用的“使用 $lookup 执行单个等值连接”部分中给出的示例数据。

以下代码示例使用 orders集合中的 item字段和 inventory集合中的 sku字段,将 orders集合中的文档与 inventory集合中的文档连接起来。

为此,该示例使用的聚合管道包含$lookup阶段,该阶段指定要从中检索数据的集合以及本地和外部字段名称。

$pipeline = [ MongoDB\Builder\Stage::lookup( from: 'inventory', localField: 'item', foreignField: 'sku', as: 'inventory_docs', ),]; /* Performs the aggregation on the orders collection */$cursor = $collection->aggregate($pipeline); foreach ($cursor as $doc) { echo json_encode($doc), PHP_EOL;}

要查看使用MongoDB PHP库创建复杂聚合管道的教程,请参阅 DEV Community 网站上的MongoDB PHP驱动程序提供更好的聚合管道支持。

要查看使用聚合构建器构建的聚合管道的更多示例,请参阅Github上PHP库源代码中的阶段类测试套件。

要学习;了解有关本指南所讨论主题的更多信息,请参阅MongoDB Server手册中的以下页面:

  • 有关聚合阶段的完整列表,请参阅 聚合阶段,详见 MongoDB Server 手册。

  • 要学习;了解如何组装聚合管道并查看示例,请参阅聚合管道。

  • 要了解有关创建管道阶段的更多信息,请参阅聚合阶段。

  • 要了解有关解释 MongoDB 操作的更多信息,请参阅解释输出和查询计划。

您可以使用MongoDB搜索功能执行全文搜索。要学习,了解更多信息,请参阅运行 MongoDB 搜索查询指南。

您可以使用MongoDB Vector Search功能对向量嵌入执行相似性搜索。要学习;了解更多信息,请参阅运行MongoDB Vector Search 查询指南。

要学习;了解有关本指南中讨论的方法的更多信息,请参阅以下API文档: