Mongoose find with multiple matches

I am new to this technology and am working with a Node and Express server that Mongoose uses. I have the following schema for a collection of documents.

var empSchema = new mongoose.Schema({
	_id: String,
	orgName: {type: String, required: true},
	locName: {type: String, required: true},
	empName: {type: String, required: true}
});
      

Run codeHide result


Here I am getting a list of location names like "NewYork", "London", "Paris" etc ... in the request and should return documents in the response like the following ....

{
result:[{locName:"NewYork",
	empList:[
		{orgName:"abc", empName:"emp1"},
		{orgName:"xyz", empName:"emp2"}]
	},
	{locName:"London",
	empList:[
		{orgName:"pkq", empName:"emp13"},
		{orgName:"mns", empName:"emp23"}]
	}]
}
      

Run codeHide result


What would be the best way to use mongoose from Node. I think making multiple queries (each with place) in mongodb is a bad idea.

Is there a way to get the expected json response with one mongoose call? Thank.

+3


source to share


2 answers


Yes, use an aggregation framework to get the desired result. Aggregation pipeline will consist of a stage , which includes documents on the field and to add fields and the array . The last statement in the stage replaces the field from the previous aggregation stream with the new field . $group

locName

$addToSet

orgName

empName

empList

$project

_id

locName

To demonstrate this concept, suppose you have a sample collection that you paste with the mongo shell:

db.employees.insert([
    {
        _id: "1",
        orgName: "abc",
        locName: "New York",
        empName: "emp1"
    },
    {
        _id: "2",
        orgName: "xyz",
        locName: "New York",
        empName: "emp2"
    },
    {
        _id: "3",
        orgName: "pkq",
        locName: "London",
        empName: "emp13"
    },
    {
        _id: "4",
        orgName: "mns",
        locName: "London",
        empName: "emp23"
    }
])

      

The following aggregation gives the desired result:

db.employees.aggregate([
    {
        "$group": {
            "_id": "$locName",
            "empList": {
                "$addToSet": {
                    "orgName": "$orgName",
                    "empName": "$empName"
                }
            }
        }
    },
    {
        "$project": {
            "_id": 0,
            "locName": "$_id",
            "empList": 1
        }
    }
])

      



Output

/* 0 */
{
    "result" : [ 
        {
            "empList" : [ 
                {
                    "orgName" : "mns",
                    "empName" : "emp23"
                }, 
                {
                    "orgName" : "pkq",
                    "empName" : "emp13"
                }
            ],
            "locName" : "London"
        }, 
        {
            "empList" : [ 
                {
                    "orgName" : "xyz",
                    "empName" : "emp2"
                }, 
                {
                    "orgName" : "abc",
                    "empName" : "emp1"
                }
            ],
            "locName" : "New York"
        }
    ],
    "ok" : 1
}

      

In Mongoose, you can use an aggregation pipeline like this:

Employee.aggregate()
        .group({
            "_id": "$locName",
            "empList": {
                "$addToSet": {
                    "orgName": "$orgName",
                    "empName": "$empName"
                }
            }
        })
        .project({
            "_id": 0,
            "locName": "$_id",
            "empList": 1
        })
        .exec(function (err, res) {
            if (err) return handleError(err);
            console.log(res); 
    });

// Or the simple aggregate method
var pipeline = [
    {
        "$group": {
            "_id": "$locName",
            "empList": {
                "$addToSet": {
                    "orgName": "$orgName",
                    "empName": "$empName"
                }
            }
        }
    },
    {
        "$project": {
            "_id": 0,
            "locName": "$_id",
            "empList": 1
        }
    }
]

Employee.aggregate(pipeline, function (err, res) {
    if (err) return handleError(err);
    console.log(res); 
});

      

+2


source


All queries when you need to group sum values, called aggregate. You can read about this in the mongo docs and the same methods have a model in Mongoose . To create a request, you can use the following code:

Employee
  .aggregate()
  .group({ _id: '$locName', empList: { $push: "$$ROOT" }})
  .exec(function (err, res) {

});

      



If you don't need to query the entire table, there is also a match method .

+1


source







All Articles