How to update document data in nested object in MongoDB? - node.js

This is default schema model :-
const UserSettings = new Schema({
ID: { type: Number, required: true, exists: false, unique : true },
UserID : Number,
Account : {
Name : String,
Email : { type: String, required: "email id is required", exists: false, unique : true },
UserName : String,
isFacebook : {type : Boolean, default : false}
},
Notification : {
Trending : {
isEmail : {type : Boolean, default : true},
isPush : {type : Boolean, default : true},
Button : {
isDaily : {type : Boolean, default : false},
isWeekly : {type : Boolean, default : false},
isOff : {type : Boolean, default : false}
}
},
Recommanded : {
isEmail : {type : Boolean, default : true},
isPush : {type : Boolean, default : true},
Button : {
isDaily : {type : Boolean, default : false},
isWeekly : {type : Boolean, default : false},
isOff : {type : Boolean, default : false}
}
}
}
});
When I save values it will enter the default fields values in schema,
"Account" : {
"Email" : "ted#gmail.com",
"isFacebook" : true,
"Name" : "ted"
},
"Notification" : {
"Trending" : {
"Button" : {
"isDaily" : false,
"isWeekly" : false,
"isOff" : false
},
"isEmail" : true,
"isPush" : true
},
"Recommanded" : {
"Button" : {
"isDaily" : false,
"isWeekly" : false,
"isOff" : false
},
"isEmail" : true,
"isPush" : true
}
}
In update case I have to passed selected arguments like only need to Update
Account{
Email : "ted1#gmail.com"
},
Notification {
Trending {
isPush : false,
}
}
Then how would I used mongo update query?
I have tried this solutions to update value but it will removed existing value :-
return UserSettings.updateOne(
{$and: [{ UserID: args.UserID },{ Status : 1 }]},
{ $push : { "Account": args.Account }},
{
upsert: true,
returnNewDocument: true
},
);
and one more this :-
return UserSettings.updateOne(
{$and: [{ UserID: args.UserID },{ Status : 1 }]},
args,
{
upsert: true,
returnNewDocument: true
},
);

Try this:
let Account = args.Account
let condition = { $and: [ { UserID: args.UserID },{ Status : 1 }]}, { 'Account.Email': args.Account.Email }] }; // here check email in sub document
UserSettings.updateOne(condition, { $set: { Account: Account } }).exec((err, data) => {
if (err || data.nModified == 0) {
UserSettings.updateOne({ UserID: args.UserID }, { $push: { Account: Account } }).exec((err, data) => {
return {'message':'Updated successfully','data':data}; // Send proper response as per your need
});
}
else {
return {'message':'Failed'};// Send proper response as per your need
}
});

Related

mongodb: expires not working

In mongoose 5.0.6, I'm hoping this schema to expire documents 1min after creation:
const InvitationTokenSchema = new Schema(
{
token: { type: String, required: true },
createdAt: { type: Date, default: Date.now, expires: '1m' },
userId: { type: Schema.Types.ObjectId, ref: 'User' },
},
{
usePushEach: true,
},
);
However it simply doesn't work - all documents just persists in mongo, not being removed.
In mongo shell, getIndexes() shows the following:
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "mydb.invitationtokens"
},
{
"v" : 2,
"key" : {
"createdAt" : 1
},
"name" : "createdAt_1",
"ns" : "mydb.invitationtokens",
"expireAfterSeconds" : 60,
"background" : true
}
]
What possibly could be the reason?
As I see you code, its right.
Also, the value should be String and you can use '1m' as well.
You need to update the mongoose to the latest version.
Use: npm update mongoose
For more details search for "expires" here: http://mongoosejs.com/docs/api.html

how to use Mongoose to (add to , update,delete) Nested documents

I am a fresh mongoose user and I have a small exercise I have this schema
`var BusinessSchema = mongoose.Schema({
personal_email: { type: String, required: true, unique: true },
business_name: { type: String, required: true, unique: true },
business_emails: [{ email: String, Description: String }],
business_logo: { data: Buffer, contentType: String },
//Business Services
services: [{
service_name: { type:String,required:true},
service_price: Number,
promotion_offer : Number,
service_rating : [{Clinet_username:String ,rating : Number}],
service_reviews : [{Clinet_username:String ,review : String}],
type_flag : Boolean,
available_flag : Boolean
}]
});`
what I want to do is to update or add new service or delete rating using mongoose
business.update({// something here to update service_rating },function(err,found_business)
{
}); business.update({// something here to add new service_rating },function(err,found_business)
{
}); business.update({// something here to delete service_rating },function(err,found_business)
{
});
var where_clause = { /* your where clause */ };
var service_rating = {"username", 5};
to add :
business.update(where_clause, {
'$addToSet' : {
services.service_rating : service_rating
}
}, callback);
to delete :
business.update(where_clause, {
'$pull' : {
services.service_rating : service_rating
}
}, callback);
to update :
var other_where = {services.service_rating : {"user", 5}}; // your where clause
business.update(other_where, {
'$set': {
'services.service_rating.Clinet_username' : 'newUser',
'services.service_rating.rating' : 10
}
}, callback);

Mongoose dup key

I'm getting a duplicate key error and not sure why.
I have the following schema:
var walletSchema = mongoose.Schema({
currencyName : {type : String, required : true, unique : true},
amount : {type : Number, default : 0}
}, {strict : false});
// define the schema for our user model
var userSchema = mongoose.Schema({
local : {
username : { type: String, required: true, unique: true },
password : { type: String, required: true, unique : true },
email : { type: String, required: true, unique: true },
country : { type: String, required: true },
inventory : {
food : { type : Number, default : 0},
energyDrinks : { type : Number, default : 0 }
},
wallet : [walletSchema],
lastAttackedAt : { type: Date, default: Date.now },
lastJobChange : {type: Date, default: '03/30/1988' },
lastWorked : {type: Date},
referredBy : {type : String, default : 'Admin'},
energy : { type: Number, default: 100 },
energyUpdatedAt : { type : Date, default: Date.now },
resetPasswordToken: String,
resetPasswordExpires: Date
}
},{timestamps : true});
I create a new user with this code :
...
newUser.local.username = capitalizeUser(username);
newUser.local.password = newUser.generateHash(password);
newUser.local.email = req.body.email;
newUser.local.country = req.body.country;
newUser.local.wallet.push({
// Create the default currencies
currencyName: 'Euro',
}, {
currencyName: 'Gold',
}, {
currencyName: result.countryCurrency
}
);
// save the user
newUser.save(function(err) {
if (err)
throw err;
return done(null, newUser);
});
Everything works fine for the first user however if I try to make another user I get MongoError: insertDocument :: caused by :: 11000 E11000 duplicate key error index: xyz.users.$local.wallet.currencyName_1 dup key: { : "Euro" }.
Why is this happening, doesn't each user has it's own wallet? How should I handle it, keep in mind that there are about ~230 currencies available for each user.
currencyName : {type : String, required : true}
Remove unique from there and you will be good to go. Mongo checks unique keys for collection. In your case walletSchema collection will have a lot of same values so that's why it's gives error.
As your currencyName has been set unique so it has to be different for each user you save. In fact you with this schema you won't even be able to have two users from the same country.
So to avoid this you need to remove the unique keyword from you schema and it is done. It then looks something like this.
var walletSchema = mongoose.Schema({
currencyName : {type : String, required : true},
amount : {type : Number, default : 0}
}, {strict : false});

Data not populating in mongoose

here is my schema
var employee =
{
empCode : { type : String , unique: true , required : true },
firstName : { type : String , required : true },
lastName : { type : String },
email : { type : String },
DOJ :{ type : Date , default: Date.now },
DOB :{ type : Date },
phoneNo : { type : String },
authentication :
{
username : { type : String },
password : { type : String }
},
dsg :
[{
designationID: [{type : mongoose.Schema.ObjectId , ref:'designation'}],
effFrom :{ type : Date , default: Date.now },
effTo : { type : Date }
}],
grd :
{
grade : [{type : mongoose.Schema.ObjectId, ref:'grade'}],
effFrom :{ type : Date , default: Date.now },
effTo : { type : Date }
},
dpt :
{
departmentID : [{type : mongoose.Schema.ObjectId ,ref:'department'}],
effFrom :{ type : Date , default: Date.now },
effTo : { type : Date }
},
manager :
{
managerID : {type : mongoose.Schema.ObjectId , ref:'employee'},
effFrom :{ type : Date , default: Date.now },
effTo : { type : Date }
},
rol :
{
roleID : [{type : mongoose.Schema.ObjectId , ref:'role'}],
effFrom :{ type : Date , default: Date.now },
effTo : { type : Date }
},
status : {type:Boolean}
}
and i wannt to populate like this
empController.prototype.list=function(callback){
objMdlEmp.find()
.populate('designationID')
.populate('grade')
.exec(function(err, records){
if(err){
console.log(err);return;
callback(false , config.msg.SOMTHING_WRONG);
return;
}else {
callback(true , records);
}
})
};
but another document data is not showing,
when i put like this my schema then only its showing , but i need to add effFrom and effTo data also
dsg : [{type : mongoose.Schema.ObjectId , ref:'designation'}]
You cant populate embedded fields in mongoose, but you can use some workarounds
1) Keep your related data in another field like so
var employee = {
grd: {type: mongoose.Schema.ObjectId, ref: 'grade'},
grdData: {
grade: [],
effFrom: {type: Date, default: Date.now},
effTo: {type: Date}
}
};
2) Use plugins like mongoose-deep-populate
objMdlEmp.find().deepPopulate('grd.grade').exec(function (err, records) { ... });

mongoose: update field, push object in array [duplicate]

This question already has answers here:
Stop Mongoose from creating _id property for sub-document array items
(7 answers)
Closed 7 years ago.
I would like to add an element in an array in a mongo database:
db.keypairs.update( {pubkey: "1234567890"}, { $push: {listTxId: {txHash: "yyy", spent: false} } } )
The result is perfect:
listTxId" : [ { "txHash" : "xxx", "spent" : true },{ "txHash" : "yyy", "spent" : false } ]
Now I would like to do the same with node.js and mongoose
var res = wait.forMethod(Keypair,'update', {pubkey: "1234567890"}, { $push: { "listTxId": {"txHash":"zzz", "spent":false} } } );
Keypair is my node.js model for the mongoose collection:
var Keypair = require('./app/models/Keypair');
and wait.forMethod comes from a node module:
var wait = require('wait.for');
In the result, I have this "_id" element :
{ "txHash" : "zzz", "spent" : false, "_id" : ObjectId("56561571fea5d9a10a5771fd") }
QUESTION: where this ObjectId come from ? How can I get rid of it ?
UPDATE: mongoose schema:
var keypairSchema = mongoose.Schema({
userId : { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
pubkey : String,
privkeyWIF : String, // temp
balance : Number,
listTxId : [{
txHash : String,
spent : Boolean
}],
walletId : { type: mongoose.Schema.Types.ObjectId, ref: 'Wallet' },
description : { type: String, maxlength: 40 },
comments : String,
isMasterKey : { type: Boolean, default: false },
date : Date
});
Mongoose will put ids in your subdocument arrays. listTxId is a subdocument array. You can add _id: false to your schema to prevent this:
var keypairSchema = mongoose.Schema({
userId : { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
pubkey : String,
privkeyWIF : String, // temp
balance : Number,
listTxId : [{
_id: false,
txHash : String,
spent : Boolean
}],
walletId : { type: mongoose.Schema.Types.ObjectId, ref: 'Wallet' },
description : { type: String, maxlength: 40 },
comments : String,
isMasterKey : { type: Boolean, default: false },
date : Date
});

Resources