moongose nested subdocument update and delete - node.js

"_id": {
"$oid": "577cc50d10b5a6c42b26f414"
},
"firstName": "new",
"lastName": "new",
"__v": 0,
"A": [
{
"AfirstName": "AfirstName",
"AlastName": "AlastName",
"_id": {
"$oid": "577dbef2f2c9f5901f402efe"
},
"AB": [
{
"AB1firstName": "AB1firstName",
"AB1lastName": "AB1lastName",
"_id": {
"$oid": "577dd3b1495663ec2a6ca456"
}
},
{
"AB2firstName": "AB2firstName",
"AB2lastName": "AB2lastName",
"_id": {
"$oid": "577dd3bc495663ec2a6ca45a"
}
}
]
}
]
Example.update({ _id: , A._id: , A.AB._id: } ,
{"$set": {"A.$.AB": data}},
function(err,model){ console.log(model); if (err) throw err; })
This will just update the first data of AB i want to update data of AB sub-doc by _id and also want to remove the particular nested sub-doc with _id

Example.findById(_id,function(err,doc){
var result = doc.A.id(AId).AB.id(AB.ABId);
result.AB1firstName="first Name";
result.AB1lastName= "Last Name";
doc.save();
});
This will update

Each document has an _id. DocumentArrays have a special id method for looking up a document by its _id.
Example.findOne({ _id: id, A._id: Aid, A.AB._id: ABid},
function(err,model){
if (err) throw err;
var ABDoc model.A.id(Aid).AB.id(ABid);
ABDoc.AB2firstName="new value";
ABDoc.AB2lastName="new value";
model.save();
})

Related

Add new field to a specific object in mongoDB

I want to add a new field to a an object after i search the specific object,
Database looks like this:
{
"_id": {
"$oid": "608378ef1ae6b1368c6220c6"
},
"username": "paul",
"password": "cacavaca123",
"question": "q1",
"answer": "cutu"
}
{
"_id": {
"$oid": "6084c1b557f2242bcc629440"
},
"username": "mircea",
"password": "123456",
"question": "q1",
"answer": "cutu"
}
And i want to search in db for the object with username: paul and add a new field friends:[alex], I have tried this but its not working:
MongoClient.connect(uri, function(err, db) {
var dbc = db.db("chat");
dbc.collection("accounts").find({username: { $eq: user}}).aggregate( [
{
$addFields: {
frequent:[new_friend]
}
}
])
db.close();
});
Also if you know, can you tell me how to update that array of friends and add a new friend to that array?
You've to use update query to do so
Read - updateOne
Demo - https://mongoplayground.net/p/mrTg0DKtnrW
db.collection.update(
{ "username": "paul" },
{
$set: {
friends: ["alex" ]
}
})
Aggregation demo - https://mongoplayground.net/p/yiJgkrgdeHZ

How can i get populate my elements name from an array in mongoose with objectid

I'm trying to show the "name" from the "books" collection , what i'm trying to do is get "bookId" with req.paramsbookId and show it in the "history" array instead of bookId itself, thanks for any help
Method: localhost:3000/users/5f0da88156a370091499406f/borrow/5f0cd134fa4ada27787a5d85
exports.borrowBook=asyncHandler(async(req,res,next)=>{
if (req.params.bookId && req.params.id) {
bookId=req.params._id;
userId=req.params.id;
console.log("userid:"+userId);
const bookName=req.params.bookId;
User.findByIdAndUpdate( userId,{ "$push": { history: {"name":bookName} } },{new:true}).exec();
}
res.status(200).json({success:true,msg:'borrow book'});
})
Here is my books collections
{
"_id": {
"$oid": "5f0cd134fa4ada27787a5d85"
},
"name": "test",
"createdAt": {
"$date": "2020-07-13T21:25:08.261Z"
},
"slug": "test",
"__v": 0
}
This is my users collection
{
"name": "Esin Öner",
"history": [{
"name": ["5f0cd134fa4ada27787a5d85"],
"_id": {
"$oid": "5f0daa930643d71380071627"
}
}, {
"name": ["5f0cd134fa4ada27787a5d85"],
"_id": {
"$oid": "5f0dbca1c0402b1aa472b218"
}
}],
"__v": 0
}
For inserting the book name instead of book id in the history array of users document, you would require to first find the book on the basis of the bookId.
And then use the findOneAndUpdate method to update the history array of the user's document.
Also, there is an issue with your implementation of findOneAndUpdate method. The first argument of findOneAndUpdate method is an object instead of a parameter (reference).
You need to make the following changes to get the desired outcome:
exports.borrowBook=asyncHandler(async(req,res,next)=>{
try {
if (req.params.bookId && req.params.id) {
bookId=req.params._id;
userId=req.params.id;
console.log("userid:"+userId);
const bookName=req.params.bookId;
const bookRecord = await Books.find({"_id": bookId});
await User.findByIdAndUpdate( {"_id": userId},{ "$push": { history: {"name":bookRecord.name} } },{new:true}).exec();
}
} catch(e) {
console.log(e);
res.status(400).send(e);
}
res.status(200).json({success:true,msg:'borrow book'});
})

Create and update field Mongoose NodeJs

{
"_id": {
"$oid": "5a4e5b1d09fb590058bfdf86"
},
"name": "ProjectStore",
"imageURL": "none",
"longitude": 0,
"latitude": 0,
"rating": 5,
"leads": [
{
"customerId": "5a0c57db65a4931768716566",
"customerName": "testuser",
"interested": "testuser",
"_id": {
"$oid": "5a4e5b5409fb590058bfdf88"
}
}
],
"items": [
{
"name": "chat",
"categoryID": "5a0c2d292235680012bd12c9",
"semiCatID": "5a0c2d5f2235680012bd12cb",
"_id": {
"$oid": "5a4e5b3009fb590058bfdf87"
}
}
],
"__v": 2
}
I added my DB log, I try to write query that will let me update/push information to "LeadStatus".
This varible should be inside each object in the "leads" array.
I have the keys for the main id "5a4e5b1d09fb590058bfdf86"
I have the second key for the specific lead "5a4e5b5409fb590058bfdf88"
I just dont know how to write the query, for now i got this.... and got error.
Store.update(
{ _id: req.body.store._id, 'leads._id': 'req.body.lead._id', },
{ $set: { 'leads.$.LeadStatus': 'open' }, },
(err, result) => {
if (err) {
res.status(500)
.json({ error: 'Unable to update leads.', });
} else {
res.status(200)
.json(result);
}
}
);
Please Help,
Thanks.
I'm assuming you want the updated doc returned (you can choose to not do so as well, switch option new to false). You have to assign an object the value that you're updating and provide all the fields within the subfield you're updating, otherwise it will remove everything else. That's why you have to do a findOne first:
return Store.findOne({ '_id': "5a4e5b1d09fb590058bfdf86" })
.then((store) => {
if (!store) { // patient was not found for some reason
throw new Error(`Store id was not found`);
}
const options = {
new: true,
};
const updatedStore = Object.assign({}, store.toObject(), {
leads: [
{
"leadStatus": "open",
"customerId": "5a0c57db65a4931768716566",
"customerName": "testuser",
"interested": "testuser",
"_id": {
"$oid": "5a4e5b5409fb590058bfdf88"
}
}
],
});
return Store.findOneAndUpdate(
{ '_id': req.body.store._id },
{ $set: updatedStore },
options);
});
In case you're curious, you can build pre/virtual hooks off of findOneAndUpdate (no documentation for this), you won't lose anything from not using update.

How to remove a specific field by given conidtion in mongodb?

I am not being able to remove the specific eventid from the UserSchema. I searched for this and got a method using unset but that is removing the whole user while the push function is not doing anything. Is there any other way to do this?
Current UserSchema
[
{
"_id": "56593f3657e27af8245735d7",
"username": "abc",
"name": "xyz",
"__v": 0,
"favouriteid": [
{
"eventid": "5659242639e43bfc2a0836b9",
"_id": "56593f6b57e27af8245735d8"
},
{
"eventid": "5659244039e43bfc2a0836ba",
"_id": "56593f8857e27af8245735d9"
}
]
}
]
What I need-
[
{
"_id": "56593f3657e27af8245735d7",
"username": "abc",
"name": "xyz",
"__v": 0,
"favouriteid": [
{
"eventid": "5659242639e43bfc2a0836b9",
"_id": "56593f6b57e27af8245735d8"
}
]
}
]
I will be passing eventid and userid
But when I am using this code, the user gets deleted itself rather than the required field.
api.post('/removefavourites', function (req, res) {
// _id: req.body.id;
User.findById({_id: req.body.userid},
{$unset:{favouriteid: {eventid: req.body.eventid}}},
{upsert: true},
function (err) {
if(err)
return err;
else
res.json({success: true});
});
});
You can use update method with pull operation as shown below:
api.post('/removefavourites', function (req, res) {
// _id: req.body.id;
User.update({_id: req.body.userid},
{$pull:{favouriteid: {eventid: req.body.eventid}}},
function (err) {
if(err)
return err;
else
res.json({success: true});
});
});
Hope this helps :)

Node.JS + MongoDB aggregation framework average value

I have been thinking of using Node and MongoDb for a ratings system for an Android app, so far I have implemented Create, Update and Delete fine but am at a loss as to what to do when I want to get the average rating back from the DB. Here is the data structure I gave decided upon:
[
{
"_id": "1",
"ratings": [
{
"value": "5",
"user": "CoolUser1"
},
{
"value": "4",
"user": "CoolUser2"
}
]
},
{
"_id": "2",
"ratings": [
{
"value": "4",
"user": "CoolUser3"
},
{
"value": "2",
"user": "CoolUser4"
}
]
}
]
Basically what I need is the average value in ratings for a given _id.
Here is the Update method I am using to give a sense of how I have setup the mongoDB connection:
exports.updateRating = function(req, res) {
var id = req.params.id;
var rating = req.body;
console.log('Updating a rating: ' + id);
console.log(JSON.stringify(rating));
ratings.update({'_id': id},
{$push: rating},
{upsert:true},
function(err, result) {
if (err) {
console.log('Error updating rating: ' + err);
res.send({'error':'An error has occurred'});
} else {
console.log('' + result + ' document(s) updated');
res.send(rating);
}
}
);
}
Is it critical to store ratings.value as a string?
This will work, but only if you convert rating to number before safe
ratings.aggregate([
{ $match: { _id: id } },
{ $unwind: '$ratings' },
{ $group: { _id: null, avg: { $avg: '$ratings.value' } } }
], function(err, result) {
console.log(result);
db.close();
});

Resources