Mongo group method

128 views
Skip to first unread message

Gavin

unread,
Feb 26, 2011, 5:50:53 PM2/26/11
to MongoEngine Users
Hi

Is there a way to access the mongodb group method through mongoengine?

In the javascript I can

db.record.group({
key:{'id':true},
initial:{sum:0},
reduce:function(doc,prev) {prev.sum+=doc.cost}
})

but I can't see how to send that command through mongoengine. I could
send it directly through pymongo but I would rather not use two
interfaces if at all possible.

Many thanks

Gavin

JTG JTG

unread,
May 17, 2013, 5:12:26 AM5/17/13
to mongoeng...@googlegroups.com, qofda...@googlemail.com
A bit late, I just leave this here for google.

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']

Trevor Joynson

unread,
May 18, 2013, 1:24:01 PM5/18/13
to mongoeng...@googlegroups.com

Thanks, I've needed to do something similar and your way is much more elegant ;)

--
You received this message because you are subscribed to the Google Groups "MongoEngine Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mongoengine-us...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Bob Pasker

unread,
May 29, 2013, 7:52:07 AM5/29/13
to mongoeng...@googlegroups.com
this is working great for me. thank you!

Rafael Turk

unread,
Aug 23, 2013, 10:00:06 PM8/23/13
to mongoeng...@googlegroups.com, qofda...@googlemail.com
Hi Gavin,
I can't make this object work. Is this code still valid for version 0.8?
tks
Reply all
Reply to author
Forward
0 new messages