Aggregation Examples
To start, we’ll insert some example data which we can perform aggregations on:
This example shows how to use the aggregate() method to use the aggregation framework. We’ll perform a simple aggregation to count the number of occurrences for each tag in the array, across the entire collection. To achieve this we need to pass in three operations to the pipeline. First, we need to unwind the tags
array, then group by the tags and sum them up, finally we sort by count.
As python dictionaries don’t maintain order you should use or collections.OrderedDict where explicit ordering is required eg “$sort”:
Note
aggregate requires server version >= 2.1.0.
>>> from bson.son import SON
>>> pipeline = [
... {"$unwind": "$tags"},
... {"$group": {"_id": "$tags", "count": {"$sum": 1}}},
... {"$sort": SON([("count", -1), ("_id", -1)])}
... ]
>>> import pprint
>>> pprint.pprint(list(db.things.aggregate(pipeline)))
[{u'_id': u'cat', u'count': 3},
{u'_id': u'dog', u'count': 2},
{u'_id': u'mouse', u'count': 1}]
To run an explain plan for this aggregation use the method:
{u'ok': 1.0, u'stages': [...]}
See also
The full documentation for MongoDB’s aggregation framework
Another option for aggregation is to use the map reduce framework. Here we will define map and reduce functions to also count the number of occurrences for each tag in the tags
array, across the entire collection.
Our map function just emits a single (key, 1) pair for each tag in the array:
The reduce function sums over all of the emitted values for a given key:
... function (key, values) {
... var total = 0;
... for (var i = 0; i < values.length; i++) {
... total += values[i];
... }
... return total;
... }
... """)
Note
Finally, we call and iterate over the result collection:
>>> result = db.things.map_reduce(mapper, reducer, "myresults")
>>> for doc in result.find().sort("_id"):
... pprint.pprint(doc)
...
{u'_id': u'cat', u'value': 3.0}
PyMongo’s API supports all of the features of MongoDB’s map/reduce engine. One interesting feature is the ability to get more detailed results when desired, by passing full_response=True to map_reduce(). This returns the full response to the map/reduce command, rather than just the result collection:
All of the optional map/reduce parameters are also supported, simply pass them as keyword arguments. In this example we use the query parameter to limit the documents that will be mapped over:
>>> results = db.things.map_reduce(
... mapper, reducer, "myresults", query={"x": {"$lt": 2}})
>>> for doc in results.find().sort("_id"):
... pprint.pprint(doc)
...
{u'_id': u'cat', u'value': 1.0}
{u'_id': u'dog', u'value': 1.0}
You can use or collections.OrderedDict to specify a different database to store the result collection:
>>> from bson.son import SON
>>> pprint.pprint(
... db.things.map_reduce(
... mapper,
... reducer,
... out=SON([("replace", "results"), ("db", "outdb")]),
... full_response=True))
See also
The full list of options for MongoDB’s