1

I'm using MongoDB and i have the following records:

{
    name: "a",
    status: [
        { age: 15, closed: true},
        { age: 38, closed: true},
        { age: 42, closed: false},
    ]
},
{
    name: "b",
    status: [
        { age: 29, closed: true},
        { age: 5, closed: false},
    ]
}

I want to check if the before last object in status has for example age = 29.
is there anyway to do that without using aggregation ?

1 Answer 1

1

You can use $arrayElemAt and pass -2 as an argument to get before last element (-1 represents last one),

If negative, $arrayElemAt returns the element at the idx position, counting from the end of the array.

Try:

db.col.aggregate([
    {
        $addFields: {
            beforeLast: { $arrayElemAt: [ "$status", -2 ] }
        }
    },
    {
        $match: {
            "beforeLast.age": 29
        }
    },
    {
        $project: {
            beforeLast: 0
        }
    }
])

EDIT: alternatively you can use $expr with $let keyword to define a temporary variable:

db.col.find({
    $expr: {
        $eq: [
            29,
            {
                $let: {
                    vars: { beforeLast: { $arrayElemAt: [ "$status", -2 ] } },
                    in: "$$beforeLast.age"
                }
            }
        ]
    }
})
Sign up to request clarification or add additional context in comments.

6 Comments

i can't use aggregate because m using an old version of mongo. is there anyway to use a simple query with find
@Ayoubk nothing comes to my mind, I believe this syntax with negative index is only available for $arrayElemAt operator. Any possiblites of upgrading your mongo ?
i think $expr allow to use aggregate operators with simple find. i wondering if it's possible ?
@Ayoubk you are right, just modified my answer, you just need $let with $expr and it works without aggregation
@Ayoubk nothing comes to my mind at the moment, maybe you can open another question and someone might be able to help you
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.