Flask-MongoEngine & PyMongo Aggregation Query

2019-01-24 07:45发布

问题:

I am trying to make an aggregation query using flask-mongoengine, and from what I have read it does not sound like it is possible.

I have looked over several forum threads, e-mail chains and a few questions on Stack Overflow, but I have not found a really good example of how to implement aggregation with flask-mongoengine.

There is a comment in this question that says you have to use "raw pymongo and aggregation functionality." However, there is no examples of how that might work. I have tinkered with Python and have a basic application up using Flask framework, but delving into full fledged applications & connecting/querying to Mongo is pretty new to me.

Can someone provide an example (or link to an example) of how I might utilize my flask-mongoengine models, but query using the aggregation framework with PyMongo? Will this require two connections to MongoDB (one for PyMongo to perform the aggregation query, and a second for the regular query/insert/updating via MongoEngine)?

An example of the aggregation query I would like to perform is as follows (this query gets me exactly the information I want in the Mongo shell):

db.entry.aggregate([
    { '$group' : 
        { '_id' : { 'carrier' : '$carrierA', 'category' : '$category' }, 
          'count' : { '$sum' : 1 }
        }
    }
])

An example of the output from this query:

{ "_id" : { "carrier" : "Carrier 1", "category" : "XYZ" }, "count" : 2 }
{ "_id" : { "carrier" : "Carrier 1", "category" : "ABC" }, "count" : 4 }
{ "_id" : { "carrier" : "Carrier 2", "category" : "XYZ" }, "count" : 31 }
{ "_id" : { "carrier" : "Carrier 2", "category" : "ABC" }, "count" : 6 }

回答1:

The class your define with Mongoengine actually has a _get_collection() method which gets the "raw" collection object as implemented in the pymongo driver.

I'm just using the name Model here as a placeholder for your actual class defined for the connection in this example:

Model._get_collection().aggregate([
    { '$group' : 
        { '_id' : { 'carrier' : '$carrierA', 'category' : '$category' }, 
          'count' : { '$sum' : 1 }
        }
    }
])

So you can always access the pymongo objects without establishing a separate connection. Mongoengine is itself build upon pymongo.



回答2:

aggregate is available since Mongoengine 0.9. Link to the API Reference.

As there is no example whatsoever around, here is how you perform an aggregate query using aggregation framework with Mongoengine > 0.9

pipeline = [
  { '$group' : 
    { '_id' : { 'carrier' : '$carrierA', 'category' : '$category' }, 
      'count' : { '$sum' : 1 }
    }
  }]

Model.objects().aggregate(*pipeline)