I am creating a project using Node.js, where I have two models: User and Project.
Here's the Schema for Project model:
const ProjectSchema = new mongoose.Schema({
name: {
type: String,
maxlength: 50,
required: true,
},
description: {
type: String,
maxlength: 800,
required: true
},
contributors: [{
type: mongoose.Schema.Types.ObjectId,
ref: "User"
}],
});
Now, for a project, I want to check if the current user is already present in the project's contributors. If the user is not present, then add the user, otherwise, Ignore.
How can I check that in an efficient manner?
mongoose offers you the aggregate method which does pretty everything, in your case:
const projects = ProjectModel.aggregate([
{ $match: {/* query for matching a small size of projects first(you should definitely do this) */} },
{ $unwind: "$contributors" },
{ $project: { contributor: "$contributors" } }, // This stage is actually optional
{ $match: { "contributor._id": /* contributor id you want to check */ } },
{ $count: "projects" }
]);
Now you can just check the variable and see how many projects have the user in their contributors array
I tested this dataset:
[{
"_id": 1,
"name": "Project1",
"contributors": [{
"_id": 11,
"name": "user1"
}, {
"_id": 22,
"name": "user2"
}]
}, {
"_id": 2,
"name": "Project2",
"contributors": [{
"_id": 22,
"name": "user3"
}, {
"_id": 44,
"name": "user4"
}]
}]
With this query:
const projects = ProjectModel.aggregate([
{ $match: { _id: 1 } },
{ $unwind: "$contributors" },
{ $project: { contributor: "$contributors" } },
{ $match: { "contributor._id": 22 } },
{ $count: "projects" }
]);
The result:
[{
"projects": 1
}]
Query
_id is on the contributors array2 with the user id and {"_id": 2} with the user document*there is no performance problem here, it will be max 1 project i guess with that _id , you only do 1 test to see if its already contributor.
update(
{"_id": {"$eq": 1}}, //find the project
[{"$set":
{"contributors":
{"$cond":
[{"$in": [2, "$contributors._id"]}, "$contributors",
{"$concatArrays": ["$contributors", [{"_id": 2}]]}]}}}])
you need to use $addToSet when updating your project document .
$addToSet will only add element to array if it is not added .
let user_id = req.body.user_id;
let project_id = req.body.project_id;
let data_to_update = { $addToSet:{contributors: user_id}};
Project.updateOne({ _id:project_id },data_to_update).then((updated)=>{
console.log('updated =',updated);
return res.status(200).json(updated);
}).catch((err)=>{
});