Trying to update a subdocument in a parent document mongoose - node.js

i am trying to update or remove a subdocument from a parent document using mongoose.
My code:
editSubscription(req, res) {
const token = req.headers.authorization;
jwt.verify(token, req.app.get('yourSecretKey'), function (err, payload) {
userModel.update({ _id: payload.user._id, "subscriptions._id": req.params.id }, { "$set": { "subscriptions.$": req.body } }, function (err, obj) {
console.log(obj)
})
})
}
The output of the console.log is
{ n: 0, nModified: 0, ok: 1 }
How should i do this? i know if its modified the nModified returns a 1. I can't find any docs on how to approach this or solve it and all the solutions here on stackoverflow i already tried, nothing is working.
A sample of a document in my collection:
id: '5db990daa05aa90de0c8b86b',
user:
{ role: 'User',
subscriptions: [
{ active: true,
_id: '5dbad05aaf232e2bdc033339',
name: 'Basic Fit',
price: 20,
paymentDate: '07-11-2020',
created: '2019-10-31T12:15:22.360Z',
updated: '2019-10-31T12:15:22.360Z' },
{ active: true,
_id: '5dbad2568bf56255a0f39bc7',
name: 'Netflix',
price: 10,
paymentDate: '07-11-2019',
created: '2019-10-31T12:23:50.141Z',
updated: '2019-10-31T12:23:50.141Z' } ]
],
_id: '5db990daa05aa90de0c8b86b',
fullname: 'Test naam',
email: 'test1#mail.com',
password:
'$2a$10$VzBnIcVraIRdmzy6rPHOX.7gGOXToTBNISLEfi429OfpRx02FxCaO',
birthDate: '02-12-1988',
created: '2019-10-30T13:32:10.276Z',
updated: '2019-10-30T13:32:10.276Z',
__v: 0 },
payload.user._id == the verified logged in user ID
req.params.id is supposed to be the subscriptionId im trying to edit

Try this:
editSubscription(req, res) {
const token = req.headers.authorization;
jwt.verify(token, req.app.get('yourSecretKey'), function (err, payload) {
userModel.update({ _id: ObjectId(payload.user._id), "subscriptions._id": ObjectId(req.params.id) }, { "$set": { "subscriptions.$": req.body } }, function (err, obj) {
console.log(obj)
})
})
}

I tried and im getting a 500 error response back..
When i remove the 'req.params.id' and i do it like this:
userModel.updateOne({ _id: payload.user._id }, { "$set": { "subscriptions.0.price":
req.body.price} }).then(user => {
console.log(user)
}).catch(err => {
console.log(err)
})
Then it works but since i have multiple items in an array i do not want to update only the first one..
I tried using a filter in the $set operator but im getting errors all over the place..

Related

Cannot save object of array input data into mongodb

how I update my array data in nested array in node js and mongo db. when i was try to save data then massage was print but data not saved in mongo db, please check schema and back end code explain which sentence to create a problem.
// schema
mainmenu: [
{
arrname: String,
submenuarray: [
{
dishname1: {
type: String,
},
prize1: {
type: Number,
},
dishcategory1: {
type: String,
},
},
],
},
];
// back End
app.patch('/addsubmenu/:id/:mainid', async (req, res) => {
const mainid = req.params.mainid;
console.log(mainid);
const id = req.params.id;
console.log(id);
getschema
.findByIdAndUpdate(
{ _id: mainid, 'submenuarray._id': id },
{
$push: {
submenuarray: {
dishname1: req.body.dishname1,
prize1: req.body.prize1,
dishcategory1: req.body.dishcategory1,
},
},
}
)
.then((data) => {
console.log(data);
res.status(201).json(data);
})
.catch((err) => {
console.log(err);
});
});
The findByIdAndUpdate accept the id as first parameter, try to use findOneAndUpdate.
Also, set the flag { new: true} to return the updated object:
getschema
.findOneAndUpdate(
{ _id: mainid, 'submenuarray._id': id },
{
$push: {
submenuarray: {
dishname1: req.body.dishname1,
prize1: req.body.prize1,
dishcategory1: req.body.dishcategory1,
},
},
},
{ new: true }
)
.then((data) => {
console.log(data);
res.status(201).json(data);
})
.catch((err) => {
console.log(err);
});

mongoose findOneAndUpdate gives different user

I was trying to $pull an object inside my cart collections. but after I make a request and sent a specific _id it gives me a different person.
this was the _id I sent from my client side.
{ id: '62a849957410ef5849491b1b' } /// from console.log(req.params);
here's my mongoose query.
export const deleteItem = (req,res) => {
const { id } = req.params;
console.log(id);
try {
if(!mongoose.Types.ObjectId.isValid(id)) return res.status(404).json({ message: 'ID not found' });
ClientModels.findOneAndUpdate(id, {
$pull: {
cart: {
product_identifier: req.body.cart[0].product_identifier
}
}
},{
new: true
}).then(val => console.log(val)).catch(temp => console.log(temp));
} catch (error) {
res.status(404).json(error);
}
}
after the request here's the callback.
{
_id: new ObjectId("62a77ab16210bf1afd8bd0a9"),
fullname: 'Gino Dela Vega',
address: '008 Estrella.st santo cristo',
email: 'gamexgaming1997#gmail.com',
google_id: 'none',
birthday: '1997-12-30',
number: 9922325221,
gender: 'Male',
username: 'ginopogi',
password: '$2b$12$YCc1jclth.ux4diwpt7EXeqYyLOG0bEaF.wvl9hkqNVptY.1Jsuvi',
cart: [],
wishlist: [],
toBeDeliver: [],
Delivered: [],
__v: 0
}
as you guys can see after sending a specific _id to find a user...the callback gives me a different user reason that I can't pull the specific object inside cart. (the object I was trying to pull is on another user)
Probably because findOneAndUpdate expect a filter as first parameter, try to switch to findByIdAndUpdate if you want to filter by a specific _id:
export const deleteItem = (req, res) => {
...
ClientModels.findByIdAndUpdate(
id,
{
$pull: {
cart: {
product_identifier: req.body.cart[0].product_identifier,
},
},
},
{
new: true,
}
)
.then((val) => console.log(val))
.catch((temp) => console.log(temp));
} catch (error) {
res.status(404).json(error);
}
};

how can send new added item in nested object as response

I have a collection with name User in my mongodb for the example you can see in below a sample of saved user
{
_id: new ObjectId("61488f3892099143ca2b2bbc"),
name: 'test',
orders: [],
products: [
{
name: 'as',
image: '049fcd8d-f954-4aef-bd77-757af881f7c5.jpeg',
_id: new ObjectId("61531666ad63a47ed692c90b")
},
]
}
I have function with node.js that has responsible to add new product to selected user
async function addProduct(req, res, next) {
await User.findOneAndUpdate(
{ _id: req.params.userId },
{
$addToSet: {
products: {
...req.body,
image: req.file.filename,
},
},
}
);
return res.status(200).send();
}
but I want to send only new added product as response
please help me to solve this problem.
I recommend you to use the $push operator (doc):
{ $push: { <field1>: <value1>, ... } }
Using it with your example:
(async () => {
await User.findByIdAndUpdate(
'6153769ce997d65baf860cc7',
{
$push: {
products: {
name: 'as2',
image: '589fcd8d-f954-4aef-bd77-757af881f7c5.jpeg'
}
}
}
);
})();

mongoose delete from array

I need to remove the user's id from all objects in the collection except the one that was passed, in my example it is value: 'Тата', tell me how to make such a request?
console.log(result)
[
{
_id: 5fa702b2f18e5723b4c00d9f,
value: 'Тата',
vote: { '36e7da32-f818-4771-bb5e-1807b2954b5f': [Array] },
date: 2020-11-07T20:25:22.611Z,
__v: 0
}
]
console.log(req.body)
{ value: 'Тата', habalkaId: '36e7da32-f818-4771-bb5e-1807b2954b5f' }
console.log(req.user._id)
5f63a251f17f1f38bc92bdab
that's all I could do, just find
router.post('/', passport.authenticate('jwt', {session: false}), (req, res) => {
FirstName.find({value: req.body.value})
.then(result => {
if (result.length) {
console.log(result)
console.log(req.body)
console.log(req.user._id)
FirstName.find({value: {$ne: 'Слоник'}}, function (err, arr) {
arr.map(e => {
if (e.vote[req.body.habalkaId].length) {
if(e.vote[req.body.habalkaId].includes(String(req.user._id))){
console.log(e.vote[req.body.habalkaId])
}
}
})
})
} else {
new FirstName({
value: req.body.value,
vote: {[req.body.habalkaId]: [String(req.user._id)]}
}).save();
}
})
// res.json({res: req.body})
})
FirstName.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// Create Schema
const FirstNameSchema = new Schema({
value: {
type: String
},
vote: {
type: Object
},
date: {
type: Date,
default: Date.now
}
});
module.exports = FirstName = mongoose.model('firstname', FirstNameSchema);
If I've understand well, you want something like this:
db.collection.update({
"value": {
"$ne": "tata"
}
},
{
"$pull": {
"vote.array_name": "id_value"
}
},
{
multi: true
})
First of all, find all document that not match the value with the given one. Then, for each document found, delete the object from the array, using $pull where the id given matches.
Example here
Please check the payground and check if I've used the correct schema and it shows the expected output.

MongoDB projection parameter not working in findOne()

I'm trying to use a projection parameter on findOne() to extract a single field from a document (stats) but it just seems to return the whole document. I'm using version "mongodb": "^3.4.1" in Node.js
This is the document structure
{ _id: 5e563015fa9a1a0134cac3cb,
username: 'user1',
password: '1234',
email: 'user#email.com',
stats:
{ totalViewed: 122,
totalUnique: 4,
tknow: 80,
tdknow: 42,
setCnt: 78 },
progress:
[ { cardId: 1001, knowCnt: 3, dknowCnt: 4 },
{ cardId: 1016, knowCnt: 0, dknowCnt: 0 } ] }
This is the code:
var findOneDoc = function() {
db.collection("testusers").findOne(
{ username: "user1" },
{ stats: 1 }, //field to return
function(err, result) {
if (err) {
console.log("Error: ", err);
}
console.log("Success: ", result);
}
);
};
findOneDoc();
I also tried:{$project: {stats: 1}}, to no avail
Thanks
Based on the documentation the .findOne() method takes options as a second parameter and it is recommended to use projection to define fields:
db.collection("testusers").findOne(
{ username: "user1" },
{ projection: { stats: 1 } },
function(err, result) { ... }
);
with findOne operations, the second parameter passed is an options parameter, so you should pass in your projects within the options parameter, like this:
query = { username: "user1" };
options = { projection: { stats: 1 }};
db.collection("testusers").findOne(query, options)
you can do it like mick said, with findOne
await db.collection("testusers").findOne(
{ username: "user1" },
{ projection: { stats: 1 } },
function(err, result) { ... }
);
or you can do it with find, like that
await db.collection("testusers")
.find({ username: "user1" })
.limit(1)
.project(["stats"])
.toArray()
you can add fields to the array project for more fields
findOne returns a document. use find() …..

Resources