Overview
在本指南中,您可以学习;了解如何使用 Mongoid 执行聚合操作。
聚合操作处理 MongoDB 集合中的数据并返回计算结果。 MongoDB 聚合框架是 Query API 的一部分,以数据处理管道的概念为模型。 文档进入包含一个或多个阶段的管道,该管道将文档转换为聚合结果。
聚合操作的功能类似于带有装配线的汽车工厂。 装配线设有配备专用工具的工位来执行特定任务。 例如,在制造汽车时,装配线从制造车架开始。 然后,当车架移动通过装配线时,每个工位都会组装一个单独的零件。 最终产品即成品汽车。
装配线代表聚合管道,各个工位代表聚合阶段,专用工具代表表达式操作符,而成品则代表聚合结果。
比较聚合与查找操作
下表列出了使用查找操作可以执行的不同任务,同时列出了使用聚合操作可以实现的任务作为对比。聚合框架提供了扩展功能,允许您转换和操作数据。
查找操作 | 聚合操作 |
|---|---|
选择要返回的特定文档 | 选择要返回的特定文档 |
Mongoid 构建器
您可以使用 Mongoid 的高级领域特定语言(DSL) 来构建聚合管道。 DSL 支持以下聚合管道操作符:
要使用上述操作符之一创建聚合管道,请在 Criteria 的实例上调用相应的方法。 调用该方法会将聚合操作添加到 Criteria实例的 pipeline 属性中。 要运行聚合管道,请将 pipeline 属性值传递给 Collection#aggregate 方法。
例子
考虑一个数据库,其中包含一个文档集合,这些文档由以下类建模:
class Tour include Mongoid::Document embeds_many :participants field :name, type: String field :states, type: Array end class Participant include Mongoid::Document embedded_in :tour field :name, type: String end
在此示例中,Tour 模型表示游览的名称及其途经的州,Participant 模型表示参加游览的人员的姓名。
以下示例创建了一个聚合管道,该管道使用以下聚合操作输出参与者访问过的状态:
match,用于查找participants.name字段值为"Serenity"的文档unwind,解构states大量字段并输出大量中每个元素的文档group,它会按文档的states字段的值对文档进行分组project,这会提示管道仅返回_id和states字段
criteria = Tour.where('participant.name' => 'Serenity'). unwind(:states). group(_id: 'states', :states.add_to_set => '$states'). project(_id: 0, states: 1) @states = Tour.collection.aggregate(criteria.pipeline).to_json
[{"states":["OR","WA","CA"]}]
不使用构建器的聚合
您可以使用 Collection#aggregate 方法通过传入聚合操作大量来运行没有相应构建器方法的聚合操作。 使用此方法执行聚合会返回原始 BSON::Document 对象,而不是 Mongoid::Document 模型实例。
例子
考虑一个数据库,其中包含一个文档集合,这些文档由以下类建模:
class Band include Mongoid::Document has_many :tours has_many :awards field :name, type: String end class Tour include Mongoid::Document belongs_to :band field :year, type: Integer end class Award include Mongoid::Document belongs_to :band field :name, type: String end
以下示例创建了一个聚合管道,用于检索自 2000 以来进行过巡演且至少获得 1 个奖项的所有乐队:
band_ids = Band.collection.aggregate([ { '$lookup' => { from: 'tours', localField: '_id', foreignField: 'band_id', as: 'tours', } }, { '$lookup' => { from: 'awards', localField: '_id', foreignField: 'band_id', as: 'awards', } }, { '$match' => { 'tours.year' => {'$gte' => 2000}, 'awards._id' => {'$exists' => true}, } }, {'$project' => {_id: 1}}, ]) bands = Band.find(band_ids.to_a)
[ {"_id": "...", "name": "Deftones" }, {"_id": "...", "name": "Tool"}, ... ]
提示
前面的示例仅投影输出文档的 _id字段。 然后,它使用投影的结果查找文档并将它们作为 Mongoid::Document 模型实例返回。 运行聚合管道不需要此可选步骤。
更多信息
要了解如何组装聚合管道并查看示例,请参阅聚合管道。
API 文档
要进一步了解本指南所讨论的任何方法,请参阅以下 API 文档: