How can I sort then limit an array of results in mongoose?

Viewed 928

I have a user collection with tons of properties for each user. One property is an array ('guestlist_submitted') and I am trying to return the most recent 3 items in that array according to the date field.

Using Mongoose, I am able to target that specific property on the user object, but I can't seem to limit or sort them.

I've tried using slice and and a date calculation to return the most recent 3 entires but I am struggling to get it right and not sure whats wrong.

I've tried using Sort/Limit on query builder but I've learned that these dont apply to the array inside the property I am targeting despite me saying " select('guestlist_submitted') as part ofthe query builder.

When I return the result after just targeting the property on the user object, it comes as an array with an object inside and another array inside that object. I am having problems traversing down it to target that inner array to use the slice and date sort.

First try

    Users.
    find({ fbid: req.query.fbid}).
    select('guestlist_submitted -_id').
    sort({"guestlist_submitted.date": 'desc'}).
    limit(3).
    exec((err, result) => {
        if (err) throw (err));
        if (result) {

            res.send(result);

        }

Second try:

    Users.
    find({ fbid: req.query.fbid}).
    select('guestlist_submitted -_id').
    exec((err, result) => {
        if (err) res.send(JSON.stringify(err));
        if (result) {

            const slicedArr = result.guestlist_submitted.slice(0,1);

            const sortedResultArr = slicedArr.sort(function(a,b){return new Date(b.date) - new Date(a.date); });

            const newResultArr = sortedResultArr.slice(0, 2);

            res.send(newResultArr);

        }

The best I can get is 'guestlist_submitted' and the entire array, not sorted and its inside an object inside an array.

I expected the output to be the 3 most recent results from the guestlist_submitted array inside a new array that I can display on the client.

Thank you in advance for your help

EDIT - FIGURED OUT A SOLUTION

I ended up figuring out how to get what I wanted using aggregate()

Users.aggregate([

    {
        $match:  {fbid: req.query.fbid}
    },
    {
        $unwind: "$guestlist_submitted"
    },
    {
        $sort: {'guestlist_submitted.date': -1}
    },
    {
        $limit: 2
    },
    {
        $group: {_id: '$_id', guestlist_submitted: {$push: '$guestlist_submitted'}}

    },
    {
        $project: { guestlist_submitted: 1, _id: 0 }

    }


]).exec((err, result) => {
    if (err) res.send(JSON.stringify(err));
    if (result) {

        console.log(result);
        res.send(result);
    }

}); 
1 Answers

I ended up figuring out how to get what I wanted using aggregate()

Users.aggregate([

    {
        $match:  {fbid: req.query.fbid}
    },
    {
        $unwind: "$guestlist_submitted"
    },
    {
        $sort: {'guestlist_submitted.date': -1}
    },
    {
        $limit: 2
    },
    {
        $group: {_id: '$_id', guestlist_submitted: {$push: '$guestlist_submitted'}}

    },
    {
        $project: { guestlist_submitted: 1, _id: 0 }

    }


]).exec((err, result) => {
    if (err) res.send(JSON.stringify(err));
    if (result) {

        console.log(result);
        res.send(result);
    }

}); 
Related