Doc fixes, thanks @3Inc

Author:    Slam <3lnc.slam@gmail.com>
Date:      Fri Nov 28 13:10:38 2014 +0200
This commit is contained in:
Slam 2014-11-28 13:10:38 +02:00 committed by Wilson Júnior
parent 2b3bb81fae
commit 51f314e907
10 changed files with 112 additions and 71 deletions

View File

@ -23,21 +23,32 @@ arguments should be provided::
connect('project1', username='webapp', password='pwd123') connect('project1', username='webapp', password='pwd123')
URI style connections are also supported - just supply the uri as URI style connections are also supported -- just supply the URI as
the :attr:`host` to the :attr:`host` to
:func:`~mongoengine.connect`:: :func:`~mongoengine.connect`::
connect('project1', host='mongodb://localhost/database_name') connect('project1', host='mongodb://localhost/database_name')
Note that database name from uri has priority over name .. note:: Database, username and password from URI string overrides
in :func:`~mongoengine.connect` corresponding parameters in :func:`~mongoengine.connect`: ::
connect(
name='test',
username='user',
password='12345',
host='mongodb://admin:qwerty@localhost/production'
)
will establish connection to ``production`` database using
``admin`` username and ``qwerty`` password.
ReplicaSets ReplicaSets
=========== ===========
MongoEngine supports :class:`~pymongo.mongo_replica_set_client.MongoReplicaSetClient`. MongoEngine supports
To use them, please use a URI style connection and provide the `replicaSet` name in the :class:`~pymongo.mongo_replica_set_client.MongoReplicaSetClient`. To use them,
connection kwargs. please use an URI style connection and provide the ``replicaSet`` name
in the connection kwargs.
Read preferences are supported through the connection or via individual Read preferences are supported through the connection or via individual
queries by passing the read_preference :: queries by passing the read_preference ::
@ -77,16 +88,19 @@ to point across databases and collections. Below is an example schema, using
meta = {"db_alias": "users-books-db"} meta = {"db_alias": "users-books-db"}
Switch Database Context Manager Context Managers
=============================== ================
Sometimes you may want to switch the database or collection to query against
Sometimes you may want to switch the database to query against for a class for a class.
for example, archiving older data into a separate database for performance For example, archiving older data into a separate database for performance
reasons. reasons or writing functions that dynamically choose collections to write
document to.
Switch Database
---------------
The :class:`~mongoengine.context_managers.switch_db` context manager allows The :class:`~mongoengine.context_managers.switch_db` context manager allows
you to change the database alias for a given class allowing quick and easy you to change the database alias for a given class allowing quick and easy
access to the same User document across databases:: access the same User document across databases::
from mongoengine.context_managers import switch_db from mongoengine.context_managers import switch_db
@ -98,15 +112,14 @@ access to the same User document across databases::
with switch_db(User, 'archive-user-db') as User: with switch_db(User, 'archive-user-db') as User:
User(name="Ross").save() # Saves the 'archive-user-db' User(name="Ross").save() # Saves the 'archive-user-db'
.. note:: Make sure any aliases have been registered with
:func:`~mongoengine.register_connection` before using the context manager.
There is also a switch collection context manager as well. The Switch Collection
:class:`~mongoengine.context_managers.switch_collection` context manager allows -----------------
you to change the collection for a given class allowing quick and easy The :class:`~mongoengine.context_managers.switch_collection` context manager
access to the same Group document across collection:: allows you to change the collection for a given class allowing quick and easy
access the same Group document across collection::
from mongoengine.context_managers import switch_db from mongoengine.context_managers import switch_collection
class Group(Document): class Group(Document):
name = StringField() name = StringField()
@ -116,3 +129,8 @@ access to the same Group document across collection::
with switch_collection(Group, 'group2000') as Group: with switch_collection(Group, 'group2000') as Group:
Group(name="hello Group 2000 collection!").save() # Saves in group2000 collection Group(name="hello Group 2000 collection!").save() # Saves in group2000 collection
.. note:: Make sure any aliases have been registered with
:func:`~mongoengine.register_connection` or :func:`~mongoengine.connect`
before using the context manager.

View File

@ -4,7 +4,7 @@ Defining documents
In MongoDB, a **document** is roughly equivalent to a **row** in an RDBMS. When In MongoDB, a **document** is roughly equivalent to a **row** in an RDBMS. When
working with relational databases, rows are stored in **tables**, which have a working with relational databases, rows are stored in **tables**, which have a
strict **schema** that the rows follow. MongoDB stores documents in strict **schema** that the rows follow. MongoDB stores documents in
**collections** rather than tables - the principal difference is that no schema **collections** rather than tables --- the principal difference is that no schema
is enforced at a database level. is enforced at a database level.
Defining a document's schema Defining a document's schema
@ -171,15 +171,15 @@ arguments can be set on all fields:
size = StringField(max_length=3, choices=SIZE) size = StringField(max_length=3, choices=SIZE)
:attr:`help_text` (Default: None) :attr:`help_text` (Default: None)
Optional help text to output with the field - used by form libraries Optional help text to output with the field -- used by form libraries
:attr:`verbose_name` (Default: None) :attr:`verbose_name` (Default: None)
Optional human-readable name for the field - used by form libraries Optional human-readable name for the field -- used by form libraries
List fields List fields
----------- -----------
MongoDB allows the storage of lists of items. To add a list of items to a MongoDB allows storing lists of items. To add a list of items to a
:class:`~mongoengine.Document`, use the :class:`~mongoengine.fields.ListField` field :class:`~mongoengine.Document`, use the :class:`~mongoengine.fields.ListField` field
type. :class:`~mongoengine.fields.ListField` takes another field object as its first type. :class:`~mongoengine.fields.ListField` takes another field object as its first
argument, which specifies which type elements may be stored within the list:: argument, which specifies which type elements may be stored within the list::
@ -471,8 +471,16 @@ Text indexes may be specified by prefixing the field name with a **$**. ::
class Page(Document): class Page(Document):
title = StringField() title = StringField()
rating = StringField() rating = StringField()
created = DateTimeField()
meta = { meta = {
'indexes': ['title', ('title', '-rating')] 'indexes': [
'title',
('title', '-rating'),
{
'fields': ['created'],
'expireAfterSeconds': 3600
}
]
} }
If a dictionary is passed then the following options are available: If a dictionary is passed then the following options are available:
@ -690,7 +698,7 @@ defined, you may subclass it and add any extra fields or methods you may need.
As this is new class is not a direct subclass of As this is new class is not a direct subclass of
:class:`~mongoengine.Document`, it will not be stored in its own collection; it :class:`~mongoengine.Document`, it will not be stored in its own collection; it
will use the same collection as its superclass uses. This allows for more will use the same collection as its superclass uses. This allows for more
convenient and efficient retrieval of related documents - all you need do is convenient and efficient retrieval of related documents -- all you need do is
set :attr:`allow_inheritance` to True in the :attr:`meta` data for a set :attr:`allow_inheritance` to True in the :attr:`meta` data for a
document.:: document.::
@ -709,7 +717,7 @@ document.::
Working with existing data Working with existing data
-------------------------- --------------------------
As MongoEngine no longer defaults to needing :attr:`_cls` you can quickly and As MongoEngine no longer defaults to needing :attr:`_cls`, you can quickly and
easily get working with existing data. Just define the document to match easily get working with existing data. Just define the document to match
the expected schema in your database :: the expected schema in your database ::
@ -732,7 +740,7 @@ Abstract classes
If you want to add some extra functionality to a group of Document classes but If you want to add some extra functionality to a group of Document classes but
you don't need or want the overhead of inheritance you can use the you don't need or want the overhead of inheritance you can use the
:attr:`abstract` attribute of :attr:`-mongoengine.Document.meta`. :attr:`abstract` attribute of :attr:`~mongoengine.Document.meta`.
This won't turn on :ref:`document-inheritance` but will allow you to keep your This won't turn on :ref:`document-inheritance` but will allow you to keep your
code DRY:: code DRY::

View File

@ -2,7 +2,7 @@
Documents instances Documents instances
=================== ===================
To create a new document object, create an instance of the relevant document To create a new document object, create an instance of the relevant document
class, providing values for its fields as its constructor keyword arguments. class, providing values for its fields as constructor keyword arguments.
You may provide values for any of the fields on the document:: You may provide values for any of the fields on the document::
>>> page = Page(title="Test Page") >>> page = Page(title="Test Page")
@ -32,11 +32,11 @@ already exist, then any changes will be updated atomically. For example::
Changes to documents are tracked and on the whole perform ``set`` operations. Changes to documents are tracked and on the whole perform ``set`` operations.
* ``list_field.push(0)`` - *sets* the resulting list * ``list_field.push(0)`` --- *sets* the resulting list
* ``del(list_field)`` - *unsets* whole list * ``del(list_field)`` --- *unsets* whole list
With lists its preferable to use ``Doc.update(push__list_field=0)`` as With lists its preferable to use ``Doc.update(push__list_field=0)`` as
this stops the whole list being updated - stopping any race conditions. this stops the whole list being updated --- stopping any race conditions.
.. seealso:: .. seealso::
:ref:`guide-atomic-updates` :ref:`guide-atomic-updates`
@ -74,7 +74,7 @@ Cascading Saves
If your document contains :class:`~mongoengine.fields.ReferenceField` or If your document contains :class:`~mongoengine.fields.ReferenceField` or
:class:`~mongoengine.fields.GenericReferenceField` objects, then by default the :class:`~mongoengine.fields.GenericReferenceField` objects, then by default the
:meth:`~mongoengine.Document.save` method will not save any changes to :meth:`~mongoengine.Document.save` method will not save any changes to
those objects. If you want all references to also be saved also, noting each those objects. If you want all references to be saved also, noting each
save is a separate query, then passing :attr:`cascade` as True save is a separate query, then passing :attr:`cascade` as True
to the save method will cascade any saves. to the save method will cascade any saves.
@ -113,12 +113,13 @@ you may still use :attr:`id` to access the primary key if you want::
>>> bob.id == bob.email == 'bob@example.com' >>> bob.id == bob.email == 'bob@example.com'
True True
You can also access the document's "primary key" using the :attr:`pk` field; in You can also access the document's "primary key" using the :attr:`pk` field,
is an alias to :attr:`id`:: it's an alias to :attr:`id`::
>>> page = Page(title="Another Test Page") >>> page = Page(title="Another Test Page")
>>> page.save() >>> page.save()
>>> page.id == page.pk >>> page.id == page.pk
True
.. note:: .. note::

View File

@ -42,7 +42,7 @@ syntax::
Query operators Query operators
=============== ===============
Operators other than equality may also be used in queries; just attach the Operators other than equality may also be used in queries --- just attach the
operator name to a key with a double-underscore:: operator name to a key with a double-underscore::
# Only find users whose age is 18 or less # Only find users whose age is 18 or less
@ -84,19 +84,20 @@ expressions:
Geo queries Geo queries
----------- -----------
There are a few special operators for performing geographical queries. The following There are a few special operators for performing geographical queries.
were added in 0.8 for: :class:`~mongoengine.fields.PointField`, The following were added in MongoEngine 0.8 for
:class:`~mongoengine.fields.PointField`,
:class:`~mongoengine.fields.LineStringField` and :class:`~mongoengine.fields.LineStringField` and
:class:`~mongoengine.fields.PolygonField`: :class:`~mongoengine.fields.PolygonField`:
* ``geo_within`` -- Check if a geometry is within a polygon. For ease of use * ``geo_within`` -- check if a geometry is within a polygon. For ease of use
it accepts either a geojson geometry or just the polygon coordinates eg:: it accepts either a geojson geometry or just the polygon coordinates eg::
loc.objects(point__geo_within=[[[40, 5], [40, 6], [41, 6], [40, 5]]]) loc.objects(point__geo_within=[[[40, 5], [40, 6], [41, 6], [40, 5]]])
loc.objects(point__geo_within={"type": "Polygon", loc.objects(point__geo_within={"type": "Polygon",
"coordinates": [[[40, 5], [40, 6], [41, 6], [40, 5]]]}) "coordinates": [[[40, 5], [40, 6], [41, 6], [40, 5]]]})
* ``geo_within_box`` - simplified geo_within searching with a box eg:: * ``geo_within_box`` -- simplified geo_within searching with a box eg::
loc.objects(point__geo_within_box=[(-125.0, 35.0), (-100.0, 40.0)]) loc.objects(point__geo_within_box=[(-125.0, 35.0), (-100.0, 40.0)])
loc.objects(point__geo_within_box=[<bottom left coordinates>, <upper right coordinates>]) loc.objects(point__geo_within_box=[<bottom left coordinates>, <upper right coordinates>])
@ -132,23 +133,21 @@ were added in 0.8 for: :class:`~mongoengine.fields.PointField`,
loc.objects(poly__geo_intersects={"type": "Polygon", loc.objects(poly__geo_intersects={"type": "Polygon",
"coordinates": [[[40, 5], [40, 6], [41, 6], [41, 5], [40, 5]]]}) "coordinates": [[[40, 5], [40, 6], [41, 6], [41, 5], [40, 5]]]})
* ``near`` -- Find all the locations near a given point:: * ``near`` -- find all the locations near a given point::
loc.objects(point__near=[40, 5]) loc.objects(point__near=[40, 5])
loc.objects(point__near={"type": "Point", "coordinates": [40, 5]}) loc.objects(point__near={"type": "Point", "coordinates": [40, 5]})
You can also set the maximum distance in meters as well:: You can also set the maximum distance in meters as well::
loc.objects(point__near=[40, 5], point__max_distance=1000) loc.objects(point__near=[40, 5], point__max_distance=1000)
The older 2D indexes are still supported with the The older 2D indexes are still supported with the
:class:`~mongoengine.fields.GeoPointField`: :class:`~mongoengine.fields.GeoPointField`:
* ``within_distance`` -- provide a list containing a point and a maximum * ``within_distance`` -- provide a list containing a point and a maximum
distance (e.g. [(41.342, -87.653), 5]) distance (e.g. [(41.342, -87.653), 5])
* ``within_spherical_distance`` -- Same as above but using the spherical geo model * ``within_spherical_distance`` -- same as above but using the spherical geo model
(e.g. [(41.342, -87.653), 5/earth_radius]) (e.g. [(41.342, -87.653), 5/earth_radius])
* ``near`` -- order the documents by how close they are to a given point * ``near`` -- order the documents by how close they are to a given point
* ``near_sphere`` -- Same as above but using the spherical geo model * ``near_sphere`` -- Same as above but using the spherical geo model
@ -198,12 +197,14 @@ However, this doesn't map well to the syntax so you can also use a capital S ins
Post.objects(comments__by="joe").update(inc__comments__S__votes=1) Post.objects(comments__by="joe").update(inc__comments__S__votes=1)
.. note:: Due to Mongo currently the $ operator only applies to the first matched item in the query. .. note::
Due to :program:`Mongo`, currently the $ operator only applies to the
first matched item in the query.
Raw queries Raw queries
----------- -----------
It is possible to provide a raw PyMongo query as a query parameter, which will It is possible to provide a raw :mod:`PyMongo` query as a query parameter, which will
be integrated directly into the query. This is done using the ``__raw__`` be integrated directly into the query. This is done using the ``__raw__``
keyword argument:: keyword argument::
@ -213,12 +214,12 @@ keyword argument::
Limiting and skipping results Limiting and skipping results
============================= =============================
Just as with traditional ORMs, you may limit the number of results returned, or Just as with traditional ORMs, you may limit the number of results returned or
skip a number or results in you query. skip a number or results in you query.
:meth:`~mongoengine.queryset.QuerySet.limit` and :meth:`~mongoengine.queryset.QuerySet.limit` and
:meth:`~mongoengine.queryset.QuerySet.skip` and methods are available on :meth:`~mongoengine.queryset.QuerySet.skip` and methods are available on
:class:`~mongoengine.queryset.QuerySet` objects, but the prefered syntax for :class:`~mongoengine.queryset.QuerySet` objects, but the `array-slicing` syntax
achieving this is using array-slicing syntax:: is preferred for achieving this::
# Only the first 5 people # Only the first 5 people
users = User.objects[:5] users = User.objects[:5]
@ -255,7 +256,7 @@ if more than one document matched the query. These exceptions are merged into
your document definitions eg: `MyDoc.DoesNotExist` your document definitions eg: `MyDoc.DoesNotExist`
A variation of this method exists, A variation of this method exists,
:meth:`~mongoengine.queryset.Queryset.get_or_create`, that will create a new :meth:`~mongoengine.queryset.QuerySet.get_or_create`, that will create a new
document with the query arguments if no documents match the query. An document with the query arguments if no documents match the query. An
additional keyword argument, :attr:`defaults` may be provided, which will be additional keyword argument, :attr:`defaults` may be provided, which will be
used as default values for the new document, in the case that it should need used as default values for the new document, in the case that it should need
@ -266,9 +267,13 @@ to be created::
>>> a.name == b.name and a.age == b.age >>> a.name == b.name and a.age == b.age
True True
.. warning::
:meth:`~mongoengine.queryset.QuerySet.get_or_create` method is deprecated
since :mod:`mongoengine` 0.8.
Default Document queries Default Document queries
======================== ========================
By default, the objects :attr:`~mongoengine.Document.objects` attribute on a By default, the objects :attr:`~Document.objects` attribute on a
document returns a :class:`~mongoengine.queryset.QuerySet` that doesn't filter document returns a :class:`~mongoengine.queryset.QuerySet` that doesn't filter
the collection -- it returns all objects. This may be changed by defining a the collection -- it returns all objects. This may be changed by defining a
method on a document that modifies a queryset. The method should accept two method on a document that modifies a queryset. The method should accept two
@ -311,7 +316,7 @@ Should you want to add custom methods for interacting with or filtering
documents, extending the :class:`~mongoengine.queryset.QuerySet` class may be documents, extending the :class:`~mongoengine.queryset.QuerySet` class may be
the way to go. To use a custom :class:`~mongoengine.queryset.QuerySet` class on the way to go. To use a custom :class:`~mongoengine.queryset.QuerySet` class on
a document, set ``queryset_class`` to the custom class in a a document, set ``queryset_class`` to the custom class in a
:class:`~mongoengine.Document`\ s ``meta`` dictionary:: :class:`~mongoengine.Document`'s ``meta`` dictionary::
class AwesomerQuerySet(QuerySet): class AwesomerQuerySet(QuerySet):
@ -498,7 +503,7 @@ Documents may be updated atomically by using the
There are several different "modifiers" that you may use with these methods: There are several different "modifiers" that you may use with these methods:
* ``set`` -- set a particular value * ``set`` -- set a particular value
* ``unset`` -- delete a particular value (since MongoDB v1.3+) * ``unset`` -- delete a particular value (since MongoDB v1.3)
* ``inc`` -- increment a value by a given amount * ``inc`` -- increment a value by a given amount
* ``dec`` -- decrement a value by a given amount * ``dec`` -- decrement a value by a given amount
* ``push`` -- append a value to a list * ``push`` -- append a value to a list

View File

@ -35,25 +35,25 @@ Available signals include:
:class:`~mongoengine.EmbeddedDocument` instance has been completed. :class:`~mongoengine.EmbeddedDocument` instance has been completed.
`pre_save` `pre_save`
Called within :meth:`~mongoengine.document.Document.save` prior to performing Called within :meth:`~mongoengine.Document.save` prior to performing
any actions. any actions.
`pre_save_post_validation` `pre_save_post_validation`
Called within :meth:`~mongoengine.document.Document.save` after validation Called within :meth:`~mongoengine.Document.save` after validation
has taken place but before saving. has taken place but before saving.
`post_save` `post_save`
Called within :meth:`~mongoengine.document.Document.save` after all actions Called within :meth:`~mongoengine.Document.save` after all actions
(validation, insert/update, cascades, clearing dirty flags) have completed (validation, insert/update, cascades, clearing dirty flags) have completed
successfully. Passed the additional boolean keyword argument `created` to successfully. Passed the additional boolean keyword argument `created` to
indicate if the save was an insert or an update. indicate if the save was an insert or an update.
`pre_delete` `pre_delete`
Called within :meth:`~mongoengine.document.Document.delete` prior to Called within :meth:`~mongoengine.Document.delete` prior to
attempting the delete operation. attempting the delete operation.
`post_delete` `post_delete`
Called within :meth:`~mongoengine.document.Document.delete` upon successful Called within :meth:`~mongoengine.Document.delete` upon successful
deletion of the record. deletion of the record.
`pre_bulk_insert` `pre_bulk_insert`

View File

@ -14,7 +14,7 @@ MongoDB. To install it, simply run
MongoEngine. MongoEngine.
:doc:`guide/index` :doc:`guide/index`
The Full guide to MongoEngine - from modeling documents to storing files, The Full guide to MongoEngine --- from modeling documents to storing files,
from querying for data to firing signals and *everything* between. from querying for data to firing signals and *everything* between.
:doc:`apireference` :doc:`apireference`

View File

@ -428,6 +428,7 @@ class ObjectIdField(BaseField):
class GeoJsonBaseField(BaseField): class GeoJsonBaseField(BaseField):
"""A geo json field storing a geojson style object. """A geo json field storing a geojson style object.
.. versionadded:: 0.8 .. versionadded:: 0.8
""" """
@ -436,8 +437,8 @@ class GeoJsonBaseField(BaseField):
def __init__(self, auto_index=True, *args, **kwargs): def __init__(self, auto_index=True, *args, **kwargs):
""" """
:param auto_index: Automatically create a "2dsphere" index. Defaults :param bool auto_index: Automatically create a "2dsphere" index.\
to `True`. Defaults to `True`.
""" """
self._name = "%sField" % self._type self._name = "%sField" % self._type
if not auto_index: if not auto_index:

View File

@ -250,6 +250,7 @@ class Document(BaseDocument):
:param _refs: A list of processed references used in cascading saves :param _refs: A list of processed references used in cascading saves
:param save_condition: only perform save if matching record in db :param save_condition: only perform save if matching record in db
satisfies condition(s) (e.g., version number) satisfies condition(s) (e.g., version number)
.. versionchanged:: 0.5 .. versionchanged:: 0.5
In existing documents it only saves changed fields using In existing documents it only saves changed fields using
set / unset. Saves are cascaded and any set / unset. Saves are cascaded and any

View File

@ -1860,6 +1860,7 @@ class PointField(GeoJsonBaseField):
to set the value. to set the value.
Requires mongodb >= 2.4 Requires mongodb >= 2.4
.. versionadded:: 0.8 .. versionadded:: 0.8
""" """
_type = "Point" _type = "Point"
@ -1879,6 +1880,7 @@ class LineStringField(GeoJsonBaseField):
You can either pass a dict with the full information or a list of points. You can either pass a dict with the full information or a list of points.
Requires mongodb >= 2.4 Requires mongodb >= 2.4
.. versionadded:: 0.8 .. versionadded:: 0.8
""" """
_type = "LineString" _type = "LineString"
@ -1901,6 +1903,7 @@ class PolygonField(GeoJsonBaseField):
holes. holes.
Requires mongodb >= 2.4 Requires mongodb >= 2.4
.. versionadded:: 0.8 .. versionadded:: 0.8
""" """
_type = "Polygon" _type = "Polygon"
@ -1921,6 +1924,7 @@ class MultiPointField(GeoJsonBaseField):
to set the value. to set the value.
Requires mongodb >= 2.6 Requires mongodb >= 2.6
.. versionadded:: 0.9 .. versionadded:: 0.9
""" """
_type = "MultiPoint" _type = "MultiPoint"
@ -1941,6 +1945,7 @@ class MultiLineStringField(GeoJsonBaseField):
You can either pass a dict with the full information or a list of points. You can either pass a dict with the full information or a list of points.
Requires mongodb >= 2.6 Requires mongodb >= 2.6
.. versionadded:: 0.9 .. versionadded:: 0.9
""" """
_type = "MultiLineString" _type = "MultiLineString"
@ -1968,6 +1973,7 @@ class MultiPolygonField(GeoJsonBaseField):
of Polygons. of Polygons.
Requires mongodb >= 2.6 Requires mongodb >= 2.6
.. versionadded:: 0.9 .. versionadded:: 0.9
""" """
_type = "MultiPolygon" _type = "MultiPolygon"

View File

@ -402,6 +402,7 @@ class BaseQuerySet(object):
will force an fsync on the primary server. will force an fsync on the primary server.
:param _from_doc_delete: True when called from document delete therefore :param _from_doc_delete: True when called from document delete therefore
signals will have been triggered so don't loop. signals will have been triggered so don't loop.
:returns number of deleted documents :returns number of deleted documents
""" """
queryset = self.clone() queryset = self.clone()
@ -989,7 +990,7 @@ class BaseQuerySet(object):
def aggregate(self, *pipeline, **kwargs): def aggregate(self, *pipeline, **kwargs):
""" """
Perform a aggregate function based in your queryset params Perform a aggregate function based in your queryset params
:param pipeline: list of aggregation commands, :param pipeline: list of aggregation commands,\
see: http://docs.mongodb.org/manual/core/aggregation-pipeline/ see: http://docs.mongodb.org/manual/core/aggregation-pipeline/
.. versionadded:: 0.9 .. versionadded:: 0.9