Docs 菜单
Docs 主页
/ / /
Mongoid
/

通过聚合转换数据

在此页面上

  • Overview
  • 比较聚合与查找操作
  • Mongoid 构建器
  • 例子
  • 不使用构建器的聚合
  • 例子
  • 更多信息
  • API 文档

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

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

聚合操作的功能类似于带有装配线的汽车工厂。 装配线设有配备专用工具的工位来执行特定任务。 例如,在制造汽车时,装配线从制造车架开始。 然后,当车架移动通过装配线时,每个工位都会组装一个单独的零件。 最终产品即成品汽车。

装配线代表聚合管道,各个工位代表聚合阶段,专用工具代表表达式操作符,而成品则代表聚合结果

下表列出了使用查找操作可以执行的不同任务,同时列出了使用聚合操作可以实现的任务作为对比。聚合框架提供了扩展功能,允许您转换和操作数据。

查找操作
聚合操作
Select certain documents to return
Select which fields to return
Sort the results
Limit the results
Count the results
Select certain documents to return
Select which fields to return
Sort the results
Limit the results
Count the results
Rename fields
Compute new fields
Summarize data
Connect and merge data sets

您可以使用 Mongoid 的高级领域特定语言(DSL) 来构建聚合管道。 DSL 支持以下聚合管道操作符:

Operator
方法名称

$group

group

project

unwind

要使用上述操作符之一创建聚合管道,请在 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,这会提示管道仅返回 _idstates 字段

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 文档:

后退

修改查询结果