Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions snooty.toml
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
name = "mongoid"
title = "Mongoid"

intersphinx = [ "https://www.mongodb.com/docs/manual/objects.inv",
"https://www.mongodb.com/docs/atlas/objects.inv"
]
intersphinx = [
"https://www.mongodb.com/docs/manual/objects.inv",
"https://www.mongodb.com/docs/atlas/objects.inv",
]

toc_landing_pages = [
"/quick-start-rails",
"/quick-start-sinatra"
]
toc_landing_pages = ["/quick-start-rails", "/quick-start-sinatra"]

[constants]
rails-6-version = 6.0
Expand All @@ -22,3 +20,4 @@ quickstart-sinatra-app-name = "my-sinatra-app"
quickstart-rails-app-name = "my-rails-app"
feedback-widget-title = "Feedback"
server-manual = "Server manual"
api-root = "https://www.mongodb.com/docs/mongoid/master/api/Mongoid"
190 changes: 190 additions & 0 deletions source/aggregation.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
.. _mongoid-aggregation:

====================================
Transform Your Data with Aggregation
====================================

.. facet::
:name: genre
:values: reference

.. meta::
:keywords: code example, transform, pipeline

.. contents:: On this page
:local:
:backlinks: none
:depth: 1
:class: singlecol

Overview
--------

In this guide, you can learn how to use {+odm+} to perform **aggregation
operations**.

Aggregation operations process data in your MongoDB collections and return
computed results. The MongoDB Aggregation framework, which is part of the Query
API, is modeled on the concept of data processing pipelines. Documents enter a
pipeline that contains one or more stages, and this pipeline transforms the
documents into an aggregated result.

An aggregation operation is similar to a car factory. A car factory has an assembly line, which contains assembly stations with specialized tools to do specific jobs, like drills and welders. Raw parts enter the factory, and then the assembly line transforms and assembles them into a finished product.

Check failure on line 32 in source/aggregation.txt

View workflow job for this annotation

GitHub Actions / TDBX Vale rules

[vale] reported by reviewdog 🐶 [MongoDB.CommaOxford] Use the Oxford comma in ' A car factory has an assembly line, which contains assembly stations with specialized tools to do specific jobs, like drills and '. Raw Output: {"message": "[MongoDB.CommaOxford] Use the Oxford comma in ' A car factory has an assembly line, which contains assembly stations with specialized tools to do specific jobs, like drills and '.", "location": {"path": "source/aggregation.txt", "range": {"start": {"line": 32, "column": 54}}}, "severity": "ERROR"}

The **aggregation pipeline** is the assembly line, **aggregation stages** are the
assembly stations, and **operator expressions** are the specialized tools.

Aggregation Versus Find Operations
----------------------------------

You can use find operations to perform the following actions:

- Select which documents to return
- Select which fields to return
- Sort the results

You can use aggregation operations to perform the following actions:

- Run find operations
- Rename fields
- Summarize data
- Group values
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

S: use table from rust docs


{+odm+} Builders
----------------

You can construct an aggregation pipeline by using {+odm+}'s high-level
domain-specific language (DSL). The DSL supports the following aggregation
pipeline operators:

.. list-table::
:header-rows: 1
:widths: 50 50

* - Operator
- Method Name

* - :manual:`$group <reference/operator/aggregation/group/>`
- ``group()``

* - :manual:`$project <reference/operator/aggregation/project/>`
- ``project()``

* - :manual:`$unwind <reference/operator/aggregation/unwind/>`
- ``unwind()``

To create an aggregation pipeline by using one of the preceding operators, call
the corresponding method on an instance of ``Criteria``. Calling the method adds
the aggregation operation to the ``pipeline`` atrritbure of the ``Criteria``
instance. To run the aggregation pipeline, pass the ``pipeline`` attribute value
to the ``Collection#aggregate()`` method.

Example
~~~~~~~

Consider a collection that contains documents that are modeled as follows:

.. code-block:: ruby

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

The following example creates an aggregation pipeline that outputs the states a
participant has visited by using the following
aggregation operations:

- ``$match``, which find documents in which the ``participants.name`` field
value is ``"Serenity"``
- ``$unwind``, which deconstructs the ``states`` array field and outputs a
document for each element in the array
- ``$group``, which groups the documents by the value of their ``states`` field
- ``$project``, which prompts the pipeline to return only the ``_id`` and
``states`` fields

.. literalinclude:: /includes/aggregation/builder-dsl.rb
:language: ruby
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

S: it would be useful to show output here


Aggregation with the Ruby Driver
--------------------------------

You can use the Ruby driver to run aggregation operations that do not have
corresponding builder methods by using the
``Collection#aggregate()`` method and passing in an array of aggregation
operations. Creating the aggregation pipeline by using the Ruby driver returns
raw ``BSON::Document`` objects rather than ``Mongoid::Document`` model
instances.

Example
~~~~~~~

Consider a collection that contains documents that are modeled as follows:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Consider a collection that contains documents that are modeled as follows:
Consider a database that contains collection with documents that are modeled by the following classes:


.. code-block:: ruby

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

The following example creates an aggregation pipeline to retrieve all bands that
have toured since 2000 and have at least one award:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The following example creates an aggregation pipeline to retrieve all bands that
have toured since 2000 and have at least one award:
The following example creates an aggregation pipeline to retrieve all bands that
have toured since ``2000`` and have at least ``1`` award:


.. literalinclude:: /includes/aggregation/ruby-aggregation.rb
:language: ruby
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

S: same as above, include output


.. tip::

The preceding example projects only the ``_id`` field of the output
documents. It then uses the projected results to find the documents and return
them as ``Mongoid::Document`` model instances. This optional step is not
required to run an aggregation pipeline.

Additional Information
----------------------

To view a full list of aggregation operators, see :manual:`Aggregation
Operators. </reference/operator/aggregation/>`

To learn about assembling an aggregation pipeline and view examples, see
:manual:`Aggregation Pipeline. </core/aggregation-pipeline/>`

To learn more about creating pipeline stages, see :manual:`Aggregation
Stages. </reference/operator/aggregation-pipeline/>`

API Documentation
~~~~~~~~~~~~~~~~~

To learn more about any of the methods discussed in this
guide, see the following API documentation:

- `group() <{+api-root+}/Criteria/Queryable/Aggregable.html#group-instance_method>`__
- `project() <{+api-root+}/Criteria/Queryable/Aggregable.html#project-instance_method>`__
- `unwind() <{+api-root+}/Criteria/Queryable/Aggregable.html#unwind-instance_method>`__
6 changes: 6 additions & 0 deletions source/includes/aggregation/builder-dsl.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
criteria = Tour.where('participants.name' => 'Serenity').
unwind(:states).
group(_id: 'states', :states.add_to_set => '$states').
project(_id: 0, states: 1)

Tour.collection.aggregate(criteria.pipeline).to_a
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Were you able to test this code? I only got to_json to work

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I took this code block from the existing docs, but to_json makes more sense. Changed

21 changes: 21 additions & 0 deletions source/includes/aggregation/ruby-aggregation.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
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)
1 change: 1 addition & 0 deletions source/index.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ MongoDB in Ruby. To work with {+odm+} from the command line using
tutorials
schema-configuration
working-with-data
/aggregation
API <https://mongodb.com/docs/mongoid/master/api/>
release-notes
contributing
Expand Down
Loading