[Answer]-Mongoengine query to return matching elements from an array of the same document in a collection

1đź‘Ť

What you basically need is the aggregation framework methods from MongoDB in order to do this as there are “multiple” matches for your condition and this cannot be solved by simple query projection. The essential statement goes like this, considering multiple documents that could match the condition:

db.collection.aggregate([
    // Match only the documents that satisfy the condition
    { "$match": {
        "city": "Pune",            
        "locations": { "$regex": "^B" }
    }},

    // Unwind the array as individual documents
    { "$unwind": "$locations" },

    // Match to "filter" the array elements
    { "$match": {
        "locations": { "$regex": "^B" }
    }},

    // Group back to documents if required
    { "$group": {
        "_id": "$_id",
        "city": { "$first": "$city" },
        "locations": { "$push": "$locations" }
    }}

So that $regex match for the values of “locations” starting with “B” does the filtering work that is required. First by matching only the documents in the collection that would meet the condition, then after the $uwnind of the array in those matching documents it it used again to “filter” the actual array entries.

Optionally then you put everything back as a document with only the matching array elements in the response using $group. So with your document the result will be:

{ 
    "_id" : ObjectId("5388ae8df30090186310ed77"), 
    "city" : "Pune", 
    "locations" : [ 
        "Bhawani Peth", 
        "Bibvewadi", 
    ]
}

Note that the $regex can be modified to whatever you need or be case insensitive, but the most efficient form will be the “start with” in an exact case as is shown. So use that where possible.

This would require you to access the raw “pymongo” driver underlying MongoEngine in order to get that basic “collection” object and use the aggregate method. I’m not completely sure on the correct method to do this as sources vary, but this link may be of some help to doing that part.

👤Neil Lunn

Leave a comment