1

how to get data in mongoose where last element in array? I have data looks like this:

[
    {
        "_id" : ObjectId("5b56eb3deb869312d85a8e69"),
        "transactionStatus" : [ 
            {
                "status" : "pending",
                "createdAt" : ISODate("2018-07-24T09:02:53.347Z")
            }, 
            {
                "status" : "process",
                "createdAt" : ISODate("2018-07-24T09:02:53.347Z")
            }
        ]
    },
    {
        "_id" : ObjectId("5b56eb3deb869312d8589765"),
        "transactionStatus" : [ 
            {
                "status" : "pending",
                "createdAt" : ISODate("2018-07-24T09:02:53.347Z")
            },
            {
                "status" : "process",
                "createdAt" : ISODate("2018-07-24T09:03:30.347Z")
            },
            {
                "status" : "done",
                "createdAt" : ISODate("2018-07-24T09:04:22.347Z")
            }
        ]
    }
]

And, I want to get data above where last object transactionStatus.status = process, so the result should be:

{
    "_id" : ObjectId("5b56eb3deb869312d85a8e69"),
    "transactionStatus" : [ 
        {
            "status" : "pending",
            "createdAt" : ISODate("2018-07-24T09:02:53.347Z")
        }, 
        {
            "status" : "process",
            "createdAt" : ISODate("2018-07-24T09:02:53.347Z")
        }
    ]
}

how to do that with mongoose?

silvia zulinka
  • 728
  • 3
  • 18
  • 39

2 Answers2

1

You can use $expr (MongoDB 3.6+) inside of match. Using $let and $arrayElemAt passing -1 as second argument you can get the last element as a temporary variable and then you can compare the values:

db.col.aggregate([
    {
        $match: {
            $expr: {
                $let: {
                    vars: { last: { $arrayElemAt: [ "$transactionStatus", -1 ] } },
                    in: { $eq: [ "$$last.status", "process" ] } 
                }
            }
        }
    }
])

The same result can be achieved for lower versions of MongoDB using $addFields and $match. You can add $project then to remove that temporary field:

db.col.aggregate([
    {
        $addFields: {
            last: { $arrayElemAt: [ "$transactionStatus", -1 ] }
        }
    },
    {
        $match: { "last.status": "process" }
    },
    {
        $project: { last: 0 }
    }
])
mickl
  • 48,568
  • 9
  • 60
  • 89
0

//Always update new status at Position 0 using $position operator

db.update({
    "_id": ObjectId("5b56eb3deb869312d85a8e69")
},
    {
        "$push": {
            "transactionStatus": {
                "$each": [
                    {
                        "status": "process",
                        "createdAt": ISODate("2018-07-24T09:02:53.347Z")
                    }
                ],
                "$position": 0
            }
        }
    }
)

//Your Query for checking first element status is process

db.find(
    {
        "transactionStatus.0.status": "process"
    }
)

refer $position, $each

Ratan Uday Kumar
  • 5,738
  • 6
  • 35
  • 54