How to use Group with Mongoose Search?

I have a collection named "listing" with fields like and . metadata is an object containing an object , and a string. metadata

status

user

status

The structure looks like this:

{"status": "Active", "metadata": {"user": {"urlProfile": "," averageRating ": 5," reviewCount ": 2," userId ":" 1244324 "}}}

The status field now has the same values ​​as and . I need to group by this status and filter with userId. so i have a function inside helper like below, "Active"

"Inactive"

 query: function (model, conditon, options) {
            console.log(conditon, options);
            return new Promise(function (resolve, reject) {
                options = options || {};

                model.find(conditon, {}, options).exec(function (error, data) {
                    if (error) {
                        reject(error);
                    }
                    resolve(data);
                })
            })
        }

      

The question is how to pass the group along with the user id and request the required data. Right now my part of the request looks like this:

return dbService.query(sellerModel, {
                    'metadata.user.userId': userIdRetrieved
                }, {});

      

how can i pass a group conditionally? i searched for a sample, so far haven't found any solution.

Sample collection enter image description here

Expected Result:

[{
  "Status": "Active",
  "Results": {
    "user": {
      "urlProfile": "",
      "averageRating": 5,
      "reviewCount": 2,
      "userId": "1244324"
    }
  }
}
,
{
  "Status": "InActive",
  "Results": {
    "user": {
      "urlProfile": "",
      "averageRating": 5,
      "reviewCount": 2,
      "userId": "1244324"
    }
  }
}]

      

+3


source to share


1 answer


To get the desired result, you will need to use a method as it offers operators that allow you to concatenate documents and return a specified result. aggregate

Consider building a pipeline that consists of a step by which you sum the average rating through , s, and other fields in the group using or . Your group by key is a sub-document with two fields Status and userId. $group

$avg

reviewCount

$sum

$first

$last

The final step will allow you to transform the result from the above grouped aggregates into the desired form and the method returns a query that can then be called to retrieve . $project

aggregate()

exec()

Promise




To explain the above structure, follow this example:

query: function (model, conditon, options) {
    console.log(conditon, options);
    options = options || {};
    return model.aggregate([
        { "$match": conditon },
        {
            "$group": {
                "_id": { 
                    "Status": "$status", 
                    "userId": "$metadata.user.userId" 
                },
                "urlProfile": { "$first": "$metadata.user.urlProfile" },
                "averageRating": { "$avg": "$metadata.user.averageRating" },
                "reviewCount": { "$sum": "$metadata.user.reviewCount" }
            }
        },
        {
            "$project": {
                "_id": 0,
                "Status": "$_id.Status",
                "Results": {
                    "user": {
                        "averageRating": "$averageRating",
                        "reviewCount": "$reviewCount",
                        "userId": "$_id.userId"
                    }
                }
            }
        }
    ]).exec();      
}

      

+2


source







All Articles