Skip to content

Commit 27873d2

Browse files
DOCSP-42767 Aggregation (#57)
1 parent ca16168 commit 27873d2

File tree

8 files changed

+269
-211
lines changed

8 files changed

+269
-211
lines changed

snooty.toml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
name = "mongoid"
22
title = "Mongoid"
33

4-
intersphinx = [ "https://www.mongodb.com/docs/manual/objects.inv",
5-
"https://www.mongodb.com/docs/atlas/objects.inv"
6-
]
4+
intersphinx = [
5+
"https://www.mongodb.com/docs/manual/objects.inv",
6+
"https://www.mongodb.com/docs/atlas/objects.inv",
7+
]
78

89
toc_landing_pages = [
910
"/quick-start-rails",
@@ -24,4 +25,5 @@ quickstart-sinatra-app-name = "my-sinatra-app"
2425
quickstart-rails-app-name = "my-rails-app"
2526
feedback-widget-title = "Feedback"
2627
server-manual = "Server manual"
27-
api = "https://www.mongodb.com/docs/mongoid/master/api"
28+
api-root = "https://www.mongodb.com/docs/mongoid/master/api/Mongoid"
29+
api = "https://www.mongodb.com/docs/mongoid/master/api"

source/aggregation.txt

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
.. _mongoid-aggregation:
2+
3+
====================================
4+
Transform Your Data with Aggregation
5+
====================================
6+
7+
.. facet::
8+
:name: genre
9+
:values: reference
10+
11+
.. meta::
12+
:keywords: code example, transform, pipeline
13+
14+
.. contents:: On this page
15+
:local:
16+
:backlinks: none
17+
:depth: 2
18+
:class: singlecol
19+
20+
Overview
21+
--------
22+
23+
In this guide, you can learn how to use {+odm+} to perform **aggregation
24+
operations**.
25+
26+
Aggregation operations process data in your MongoDB collections and return
27+
computed results. The MongoDB Aggregation framework, which is part of the Query
28+
API, is modeled on the concept of data processing pipelines. Documents enter a
29+
pipeline that contains one or more stages, and this pipeline transforms the
30+
documents into an aggregated result.
31+
32+
Aggregation operations function similarly to car factories with assembly
33+
lines. The assembly lines have stations with specialized tools to
34+
perform specific tasks. For example, when building a car, the assembly
35+
line begins with the frame. Then, as the car frame moves through the
36+
assembly line, each station assembles a separate part. The result is a
37+
transformed final product, the finished car.
38+
39+
The assembly line represents the *aggregation pipeline*, the individual
40+
stations represent the *aggregation stages*, the specialized tools
41+
represent the *expression operators*, and the finished product
42+
represents the *aggregated result*.
43+
44+
Compare Aggregation and Find Operations
45+
---------------------------------------
46+
47+
The following table lists the different tasks you can perform with find
48+
operations, compared to what you can achieve with aggregation
49+
operations. The aggregation framework provides expanded functionality
50+
that allows you to transform and manipulate your data.
51+
52+
.. list-table::
53+
:header-rows: 1
54+
:widths: 50 50
55+
56+
* - Find Operations
57+
- Aggregation Operations
58+
59+
* - | Select *certain* documents to return
60+
| Select *which* fields to return
61+
| Sort the results
62+
| Limit the results
63+
| Count the results
64+
- | Select *certain* documents to return
65+
| Select *which* fields to return
66+
| Sort the results
67+
| Limit the results
68+
| Count the results
69+
| Rename fields
70+
| Compute new fields
71+
| Summarize data
72+
| Connect and merge data sets
73+
74+
{+odm+} Builders
75+
----------------
76+
77+
You can construct an aggregation pipeline by using {+odm+}'s high-level
78+
domain-specific language (DSL). The DSL supports the following aggregation
79+
pipeline operators:
80+
81+
.. list-table::
82+
:header-rows: 1
83+
:widths: 50 50
84+
85+
* - Operator
86+
- Method Name
87+
88+
* - :manual:`$group <reference/operator/aggregation/group/>`
89+
- ``group()``
90+
91+
* - :manual:`$project <reference/operator/aggregation/project/>`
92+
- ``project()``
93+
94+
* - :manual:`$unwind <reference/operator/aggregation/unwind/>`
95+
- ``unwind()``
96+
97+
To create an aggregation pipeline by using one of the preceding operators, call
98+
the corresponding method on an instance of ``Criteria``. Calling the method adds
99+
the aggregation operation to the ``pipeline`` atrritbure of the ``Criteria``
100+
instance. To run the aggregation pipeline, pass the ``pipeline`` attribute value
101+
to the ``Collection#aggregate()`` method.
102+
103+
Example
104+
~~~~~~~
105+
106+
Consider a database that contains a collection with documents that are modeled by
107+
the following classes:
108+
109+
.. code-block:: ruby
110+
111+
class Tour
112+
include Mongoid::Document
113+
114+
embeds_many :participants
115+
116+
field :name, type: String
117+
field :states, type: Array
118+
end
119+
120+
class Participant
121+
include Mongoid::Document
122+
123+
embedded_in :tour
124+
125+
field :name, type: String
126+
end
127+
128+
In this example, the ``Tour`` model represents the name of a tour and the states
129+
it travels through, and the ``Participant`` model represents the name of a
130+
person participating in the tour.
131+
132+
The following example creates an aggregation pipeline that outputs the states a
133+
participant has visited by using the following
134+
aggregation operations:
135+
136+
- ``match()``, which find documents in which the ``participants.name`` field
137+
value is ``"Serenity"``
138+
- ``unwind()``, which deconstructs the ``states`` array field and outputs a
139+
document for each element in the array
140+
- ``group()``, which groups the documents by the value of their ``states`` field
141+
- ``project()``, which prompts the pipeline to return only the ``_id`` and
142+
``states`` fields
143+
144+
.. io-code-block::
145+
146+
.. input:: /includes/aggregation/builder-dsl.rb
147+
:language: ruby
148+
149+
.. output::
150+
151+
[{"states":["OR","WA","CA"]}]
152+
153+
Aggregation without Builders
154+
----------------------------
155+
156+
You can use the ``Collection#aggregate()`` method to run aggregation operations that do not have
157+
corresponding builder methods by passing in an array of aggregation
158+
operations. Using this method to perform the aggregation returns
159+
raw ``BSON::Document`` objects rather than ``Mongoid::Document`` model
160+
instances.
161+
162+
Example
163+
~~~~~~~
164+
165+
Consider a database that contains a collection with documents that are modeled
166+
by the following classes:
167+
168+
.. code-block:: ruby
169+
170+
class Band
171+
include Mongoid::Document
172+
has_many :tours
173+
has_many :awards
174+
field :name, type: String
175+
end
176+
177+
class Tour
178+
include Mongoid::Document
179+
belongs_to :band
180+
field :year, type: Integer
181+
end
182+
183+
class Award
184+
include Mongoid::Document
185+
belongs_to :band
186+
field :name, type: String
187+
end
188+
189+
The following example creates an aggregation pipeline to retrieve all bands that
190+
have toured since ``2000`` and have at least ``1`` award:
191+
192+
.. io-code-block::
193+
194+
.. input:: /includes/aggregation/ruby-aggregation.rb
195+
:language: ruby
196+
197+
.. output::
198+
199+
[
200+
{"_id": "...", "name": "Deftones" },
201+
{"_id": "...", "name": "Tool"},
202+
...
203+
]
204+
205+
.. tip::
206+
207+
The preceding example projects only the ``_id`` field of the output
208+
documents. It then uses the projected results to find the documents and return
209+
them as ``Mongoid::Document`` model instances. This optional step is not
210+
required to run an aggregation pipeline.
211+
212+
Additional Information
213+
----------------------
214+
215+
To view a full list of aggregation operators, see :manual:`Aggregation
216+
Operators. </reference/operator/aggregation/>`
217+
218+
To learn about assembling an aggregation pipeline and view examples, see
219+
:manual:`Aggregation Pipeline. </core/aggregation-pipeline/>`
220+
221+
To learn more about creating pipeline stages, see :manual:`Aggregation
222+
Stages. </reference/operator/aggregation-pipeline/>`
223+
224+
API Documentation
225+
~~~~~~~~~~~~~~~~~
226+
227+
To learn more about any of the methods discussed in this
228+
guide, see the following API documentation:
229+
230+
- `group() <{+api-root+}/Criteria/Queryable/Aggregable.html#group-instance_method>`__
231+
- `project() <{+api-root+}/Criteria/Queryable/Aggregable.html#project-instance_method>`__
232+
- `unwind() <{+api-root+}/Criteria/Queryable/Aggregable.html#unwind-instance_method>`__
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
criteria = Tour.where('participant.name' => 'Serenity').
2+
unwind(:states).
3+
group(_id: 'states', :states.add_to_set => '$states').
4+
project(_id: 0, states: 1)
5+
6+
@states = Tour.collection.aggregate(criteria.pipeline).to_json
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
band_ids = Band.collection.aggregate([
2+
{ '$lookup' => {
3+
from: 'tours',
4+
localField: '_id',
5+
foreignField: 'band_id',
6+
as: 'tours',
7+
} },
8+
{ '$lookup' => {
9+
from: 'awards',
10+
localField: '_id',
11+
foreignField: 'band_id',
12+
as: 'awards',
13+
} },
14+
{ '$match' => {
15+
'tours.year' => {'$gte' => 2000},
16+
'awards._id' => {'$exists' => true},
17+
} },
18+
{'$project' => {_id: 1}},
19+
])
20+
21+
bands = Band.find(band_ids.to_a)

0 commit comments

Comments
 (0)