lapsus
lapsus

Reputation: 3035

MongoDb filter on value of the last element in an array

The following query is not valid. Can anyone please point me to the error?

I am trying to filter on all documents where the last item in the Progress array has a given state - for example "Done".

db.logdata.aggregate(
    [
        { "$match": { "ProcessingInfo.Progress" : { "$exists": true } } },
        { "$redact":
            {
                "$cond": {
                   "if": { "$eq": [ { "$arrayElemAt": [ "$ProcessingInfo.Progress.State", -1 ], "Done" } ] },
                   "then": "$$KEEP",
                   "else": "$$PRUNE"
                }
            }
        }

    ]
)

Sample document (which should be matched - because the last State in Progress array is "InProgress"):

{ 
    "_id" : ObjectId("578fa85bb29339a1fa6d6109"), 
    "ProcessingInfo" : {
        "DateStarted" : ISODate("2016-08-06T16:55:58.294+0000"), 
        "Attempt" : NumberInt(1), 
        "LastState" : "Failed", 
        "Progress" : [
            {
                "State" : "Failed", 
                "StateDescription" : ""
            }, 
            {
                "State" : "Success", 
                "StateDescription" : ""
            }, 
            {
                "State" : "Done", 
                "StateDescription" : ""
            }, 
            {
                "State" : "InProgress", 
                "StateDescription" : ""
            }
        ]
    }
}

To kind of "circumvent" this problem I have an extra field in the document root "LastState" - is that maybe the way to go (complexity-wise)?

Upvotes: 0

Views: 680

Answers (1)

Nicolas
Nicolas

Reputation: 2231

Your query has a little syntax error: your "Done" should be in the $eq array, not in the object containing $arrayElemAt definition. The following query (optimised to filter out documents without the expected State anywhere in the ProcessInfo.Progress array thanks to what Styvane suggested) should return your example document:

[
    { "$match": { "ProcessingInfo.Progress.State" : "InProgress" } },
    { "$redact":
        {
            "$cond": {
               "if": { "$eq": [ { "$arrayElemAt": [ "$ProcessingInfo.Progress.State", -1 ] }, "InProgress" ] },
               "then": "$$KEEP",
               "else": "$$PRUNE"
            }
        }
    }
]

Upvotes: 0

Related Questions