Mongoose MongoDB updating a nested array - node.js

I have the following schema and I'm trying to update the heart_rates and glucose_levels arrays by adding a new entry:
"days": [
{
"day": "16-12-2020",
"data": {
"average_score": 80,
"metabolic_score": 80,
"cardio_score": 80,
"heart_rates": [{
"start_date": "timestamp",
"end_date": "timestamp",
"value": 100
}],
"glucose_levels": [{
"start_date": "timestamp",
"end_date": "timestamp",
"value": 100
}],
"weekly_health_recap": {
"id": "",
"start_date": "timestamp",
"end_date": "timestamp",
"rating": "Excellent"
},
"summaries": [{
"type": "meal",
"actions": [
"sweets", "fruits"
],
"title": "",
"start_date": "",
"end_date": ""
}],
"articles": [{
"id": "",
"name": "",
"text": "",
"image_url": ""
}]
}
}
]
I tried various solutions, however they didn't give the expected results.
Currently, I'm using the following code to find if there is an existing entry for the day, if there is not, I'm creating it using findByIdAndUpdate and upsert, if there is already a day entry then I'm using update and push to add a new entry in the heart_rates array. The problem is that the update inserts the new entry in some other day entry and not the one that I'm querying for.
exports.updateDayHeartrate = async (req, res) => {
User.find({ "_id": req.body._id, "days.day": req.body.day}, function (err, docs) {
if (err){
return done(err);
}
if (docs.length > 0) {
User.update({"_id": req.body._id, "days.day": req.body.day},
{$push: {"days.0.data.heart_rates": req.body.data}},
(err, user) => {
if (err) {
res.status(500).send({ message: err });
return;
}
else if (user) {
res.status(200).send("Updated!")
}
}
)
}
else{
User.findByIdAndUpdate(req.body._id,
{$push: {"days": {"day": req.body.day, "data": {"heart_rates": req.body.data}}}},
{upsert:true, new:true, setDefaultsOnInsert: true},
(err, user) => {
if (err) {
res.status(500).send({ message: err });
return;
}
else if (user) {
res.status(200).send("Updated!")
}
}
);
}
});
};

Related

How to check if an object is already existing or not in mongodb array

I am making a simple api which has like document of each post.The like post has array of object of likes of that post.I want to like object into likes only if the document is not exist and if exist remove the object from likes array.I have use element match operator
but it does not work.How can I achieve this.Thanks in advance.
The code is
router.post("/like",(req,res)=>{
likeModel.find({ postId: req.body.postId }, async (err, doc) => {
console.log(req.body.postId)
console.log(doc.length+"s ");
if (!doc.length) {
const like = new likeModel({
postId: req.body.postId,
likes: [
{
userId: userId,
isNotified: isNotified,
},
],
});
await like.save((err, doc) => {
if (err) res.json({ "message": "error" });
else res.json(doc);
});
}
if (err) {
res.json({ "message": "error"});
}
else{
likeModel.find({
postId:req.body.postId,
likes:{
$elemMatch:{
userId:req.body.userId
}
}
},(err,doc)=>{
console.log(doc.length)
if(err){
res.json({"message":"error"})
}
else if(!doc.length){
likeModel.updateOne(
{ _Id: req.body.postId },
{
$push: {
likes:req.body.likes
},
},
(err, doc) => {
if (err) res.json({ "message": "err" });
else res.json(doc);
}
);
}
else{
likeModel.updateOne({
postId:req.body.postId
},{
"$pull":{
"likes":{
"userId":req.body.userId
}
}
},(err,doc)=>{
if(err){
res.json({"message":err})
}
else{
res.json(doc)
}
}
)
}
}
})
})
The document looks like
[
{
"_id": "62f8556861c9b1029e7a07b8",
"postId": "62f5fb7d74033aeac1e06399",
"likes": [
{
"userId": "62f5d6bee2310e3c71e10e36",
"isNotified": true,
"_id": "62f8556861c9b1029e7a07b9"
},
{
"userId": "62f5d9c2b30ecc8ca84c0242",
"isNotified": true,
"_id": "62f865ed2a055ef17214a6ea"
},
{
"userId": "62f5d9c2b30ecc8ca84c0242",
"isNotified": true,
"_id": "62f866192a055ef17214a6f1"
},
{
"userId": "62f5d9c2b30ecc8ca84c0242",
"isNotified": true,
"_id": "62f8668c5ca6a649fc89cc3b"
},
{
"userId": "62f5d9c2b30ecc8ca84c0242",
"isNotified": true,
"_id": "62f866b3c2041b73ea8d9d8a"
},
{
"userId": "62f5d9c2b30ecc8ca84c0242",
"isNotified": true,
"_id": "62f867b6545168c7cd377b17"
},
{
"userId": "62f5d9c2b30ecc8ca84c0242",
"isNotified": true,
"_id": "62f868cf3255b839e1ca047b"
}
],
"__v": 0
},
{
"_id": "62f866192a055ef17214a6ed",
"postId": "62f5fb7e74033aeac1e0639d",
"likes": [
{
"userId": "62f5d9c2b30ecc8ca84c0242",
"isNotified": true,
"_id": "62f866192a055ef17214a6ee"
}
],
"__v": 0
}
]

trying to update nested array in mongodb

` "id": 1,
"name": "Afghanistan",
"iso3": "AFG",
"iso2": "AF",
"states": [
{
"id": 3901,
"name": "Badakhshan",
"state_code": "BDS",
"latitude": "36.73477250",
"longitude": "70.81199530",
"type": null,
"cities": [
{
"id": 52,
"name": "Ashkāsham",
"latitude": "36.68333000",
"longitude": "71.53333000"
},
dbo.collection("countries").updateOne(myquery,
{ $set: { "states.$[].cities.$[filter].name": new_name } },
{ arrayFilters: [ {"filter.name":old_city_name} ] },
async function (err, result) {
if (err) {
return res.json({ success: false, response: err.message, statusbar: err })
}
res.json({ success: true, statuscode: 200, response: result });
db.close();
});
trying to update a city name which in the states array its working but its updating every city in that particular state need some help guys
tq all

Mongoose/MongoDB PUT: Push Object to Array if Object ID is unique within Array

I want to update an array within a document, only if the object being pushed to the "items" array has a unique id within the "items" array.
{
"_id": "6039e37cb6b60f4694a16705",
"list_name": "Example Picklist",
"author_id": "6027f627141a75567cc2e0b0",
"author_name": "Test",
"items": [
{
"upcs": [
"111222333"
],
"qty": 10,
"id": "123456",
"name": "Item A"
},
{
"upcs": [
"444555666"
],
"qty": 22,
"name": "Item B",
"id": "987654"
}
],
"status": "initialized",
"__v": 0
}
For example, I should be able to add:
{
"name": "Item C",
"qty": 99,
"upcs": ["111555999"],
"id": "111111"
}
but not:
{
"name": "Item C",
"qty": 99,
"upcs": ["111555999"],
"id": "123456"
}
My put request is currently not refusing req.bodys with already existing ids, after I tried implementing JohnnyHK's answer to this question.
router.put('/:id', auth, async (req, res) => {
const item = req.body; // insert above examples
try {
let picklist = await Picklist.findById(req.params.id);
if (!picklist)
return res.status(404).json({ json: 'Picklist not found' });
picklist = await Picklist.findByIdAndUpdate(
{ _id: req.params.id, 'items.id': { $ne: item.id } },
{
$push: { items: item },
},
{ new: true }
);
res.json(picklist);
} catch (err) {
console.error(err.message);
res.status(500).json({ msg: 'Server Error' });
}
});
What am I getting wrong? At the moment it will push anything that fits with the Schema, and doesn't stop ID duplicates.
The error is that I was using
Picklist.findByIdAndUpdate()
instead of
Picklist.findOneAndUpdate()

Removing the specific object from array in mongoose and update it

Hi i am new in mongoose and mongodb. I want to remove specific object from the Array in my document and return the updated document. I have tried a lot but it always return null. Here is my document structure.
{
"role": "Student",
"skills": [
"html",
"css",
"js"
],
"_id": "5ef583198e9b23cc8c606c10",
"user": "5ee5c9ef26333935647e54bc",
"__v": 24,
"status": "Intern",
"education": [],
"internships": [
{
"current": false,
"_id": "5ef894d48f601512340f25b5",
"title": "Web",
"company": "asdfadfd",
"from": "2010-02-04T00:00:00.000Z"
},
{
"current": false,
"_id": "5ef894f31dc9413bf89c44d8",
"title": "Django",
"company": "example",
"from": "2010-02-04T00:00:00.000Z"
}
]
}
And here is my updating function
exports.deleteStudentInternship = async (req, res, next) => {
const deleteInternship = await Student.findOneAndUpdate(
{ $and: [{ user: req.user.id }, { 'internships': { $elemMatch: { _id: req.params.intern_id } } }] },
{ '$pull': { 'internships': { _id: req.params.intern_id } } },
{
new: true,
useFindAndModify: false,
},
function (error) {
if (error) return validationError(404, { internship: 'Internship id not exist' }, next)
}
);
if (!deleteInternship) {
return validationError(404, { internship: 'Internship id not exist' }, next)
}
res.status(200).json(deleteInternship);
}
Please change the pull part I mean
{ '$pull': { 'internships': { _id: req.params.intern_id } } }
to this and try:
{ '$pull': { 'internships': req.params.intern_id } }

mongoose.find() returns empty array with queried result

I need to find my data that matches the particular type. Say, I have an array of objects in my DB, with each object having it's leadType : all or leadType: blacklist. Each object has a different kind of leadType value associated with it.
I want to get the complete data that matches the particular leadType, like leadType: 'radar'.
I tried using the following query but along with the documents it matches, it also returns the empty documents that do not matches the specified projection.
This is what I tried:
exports.leads_by_type = (req, res) => {
const { lead_type } = req.body;
Lead.find({}, { leads: { $elemMatch: { leadType: lead_type }}} )
.then(data => {
if (!data || data.length === 0) {
return res.status(404).json({ message: "No data found" });
}
res.status(200).json({ message: "Data found", data });
})
.catch(err => res.status(500).json({ err }));
};
and it returns me the output as follows:
{
"message": "Data found",
"data": [
{
"_id": "5e83427079f7611bdc1e48a0",
"leads": [
{
"education": {
"school": "happy kids corner",
"graduation": "some school"
},
"currentPosition": {
"title": "Salesforce developer",
"endDate": "currently working",
"employmentType": "full-time",
"industry": "information technology"
},
"location": {
"state": "delhi",
"country": "india"
},
"leadType": "radar",
"name": "Ben",
"mobile": 1524524678,
"_id": "5e83427079f7611bdc1e489e"
}
]
},
{
"_id": "5e84cb4fb59fdd1644e7c226",
"leads": [
{
"education": {
"school": "happy kids corner",
"graduation": "some school"
},
"currentPosition": {
"title": "Salesforce developer",
"endDate": "currently working",
"employmentType": "full-time",
"industry": "information technology"
},
"location": {
"state": "delhi",
"country": "india"
},
"leadType": "radar",
"name": "joey",
"mobile": 1524524678,
"_id": "5e84cb4fb59fdd1644e7c224"
}
]
},
{
"_id": "5e84cb70b59fdd1644e7c229",
"leads": []
},
{
"_id": "5e84cb88b59fdd1644e7c22c",
"leads": []
},
{
"_id": "5e84cbb7b59fdd1644e7c232",
"leads": []
},
{
"_id": "5e84cbd9b59fdd1644e7c235",
"leads": [
{
"education": {
"school": "happy kids corner",
"graduation": "some school"
},
"currentPosition": {
"title": "Salesforce developer",
"endDate": "currently working",
"employmentType": "full-time",
"industry": "information technology"
},
"location": {
"state": "delhi",
"country": "india"
},
"leadType": "radar",
"name": "rhea",
"mobile": 1524524678,
"_id": "5e84cbd9b59fdd1644e7c234"
}
]
}
]
}
Please help me out to fix remove these empty objects from the data output
Edit: Adding my DB screenshot:
If you want to match only the documents with leadType equals to radar you should specify this in the find condition.
exports.leads_by_type = (req, res) => {
const { lead_type } = req.body;
Lead.find({ 'leads.leadType': lead_type })
.then(data => {
if (!data || data.length === 0) {
return res.status(404).json({ message: "No data found" });
}
res.status(200).json({ message: "Data found", data });
})
.catch(err => res.status(500).json({ err }));
};
find({ leads: { $elemMatch: { leadType: lead_type }}} )
You can try the above query.
{} you had used empty object along with your condition in find which is the root cause behind the fetched empty data.

Resources