A bit late, but may be useful for others :) Add mixin to your models:
class AdditionalMethods(object):
@classmethod
def aggregate(cls, pipeline):
"""
Perform an aggregation using the aggregation framework on this collection.
:param cls:
:param pipeline: a single command or list of aggregation commands
:return: PyMongo stuff (dict with "ok" and "result"...)
"""
collection = _get_db()[cls._get_collection_name()]
return collection.aggregate(pipeline)
@classmethod
def group(cls, key, condition, initial, reduce_f, finalize_f=None):
"""
Perform a query.
:param key: fields to group by
:param condition: specification of rows to be considered (as a :meth:`find` query specification)
:param initial: initial value of the aggregation counter object
:param reduce_f: aggregation function as a JavaScript string
:param finalize_f: function to be called on each object in output list
:return: an array of grouped items
"""
collection = _get_db()[cls._get_collection_name()]
return collection.group(key, condition, initial, reduce_f, finalize_f)
This will allow you to call pyMongo methods indirectly:
result = Product.group(key={'path': 1},
condition={"path": {"$in": [1,2,3]}},
initial={"products": [], "total": 0},
reduce_f="""
function (curr, result) {
result.products.push(curr.rn);
result.total++;
}""",
finalize_f=None)
result = Product.aggregate([
{ "$match": {'path' : { '$in' : [self.rn] } } },
{ "$group": {"_id": facets_all_group, "count": { "$sum" : 1 }} },
{ "$sort": {"count":-1} }
])['result']