Updating Particular field in Nodejs - node.js

I wanted to update the field data only ,but my code it adding an object each time i am calling update api.I have gone through many sites and found out updateOne is the method but couldnt end up undersatnding how to implement here.I am quite new to node so any help would be appreciated.
const update=(req,res)=>{
console.log(req);
models.detailsSchema.findByIdAndUpdate(req.body.vehicleId,req.body.data,{new:true}).then((msg,err)=>{
if(err)
res.status(400).json({err})
res.status(200).json({
"resCode":"0000",
"resStatus":"Success",
"resMsg":msg
})
});
}

Looks like you're using Mongoose connected to a MongoDB instance? If that's the case, Schema.findByIdAndUpdate works on the primary key or ObjectId of the record you're trying to update. To make this code work, if my assumptions are correct, change to this:
models.detailsSchema.findByIdAndUpdate(req.body._id, req.body.data, { new:true })
Of course, you're going to want to put in some check to make sure _id is defined if this is a create/update route.

Related

How to Determine if a Document was Actually Changed During Update in MongoDB

I am using the Mongoose driver with NodeJS. I have quite a simple update call whose purpose is to sync an external source of meetings to my database:
collection.update({ meeting_id: doc.meeting_id}, newDoc, {upsert:true})
The object returned determines whether or not an update or an insert occurred. This works perfectly. My issue is that I must determine if an actual change occurred. When you update a document with itself, MongoDB treats this in exactly the same way as if all fields were changed.
So my question is: Is there any good way to tell if anything actually changed? I could search for each document then compare each field manually, but this seems like a poor (and slow) solution.
you can use findAndModify which will return updated results as compared to update which will return no of updated records.
collection.findAndModify(
{ meeting_id: doc.meeting_id},
newDoc,
{ new: true },
function (err, documents) {
res.send({ error: err, affected: documents });
}
);

MongoDB and Mongoose - One to Many Relationships

I'm having a devil of a time understanding the one to many relationship options in MongoDB. I have a fairly simple use-case that I want to prove out, and I can't seem to find any good step-by-steps with my Google (and Stack Overflow)-Fu.
If I access mongo's command line tool, insert a document into the "users" collection with a String array of role_id that corresponds to the _id in the "roles" collection ... how do I tie all of it together on the mongoose side? When I use the findOne method, it just seems to pull the "role_id"s as is, so I know I must be missing something.
If I put all of these roles into the users without any reference what so ever, what happen if I needed to enable or disable roles? Would I need to update every single relevant role in every single user?
Thanks muchly for the assistance and patience for another new Mongoer!
According to your explanation you just forgot to use 'populate' in your query. Please note that results will not contain linked document, so you need to use 'populate' in order to let mongoose know - 'Hey, I want to pull info about this role as well'.
Example:
//promises
User
.findOne(<searchQuery>)
.populate('roles')
.exec()
.then(function(foundUser){
return foundUser; //do something with results (foundUser)
})
.onReject(function(err){
throw err; //do something with error
});
//callbacks
User
.findOne(<searchQuery>)
.populate('roles')
.exec(function(err, foundUser){
if(err){
throw err; //do something with error
} else {
//do something with results (foundUser)
}
});
Please check the following links:
http://mongoosejs.com/docs/2.7.x/docs/populate.html
http://mongoosejs.com/docs/populate.html

In mongoose pre middleware, how do i access the update query?

I am trying to use the new unstable version of mongoose >4.0.0 to validate update queries.
say that i want to update a schema using the following query
schema.update({_id:'blah'},{a:'blah'},function(err){
//do your thing
})
so lets say i have the following schema,
var schema = new Schema({
a:{type:String}
});
schema.pre('update',function(next){
var findQuery=this._conditions; // gives {_id:'blah'}
// how do i get {a:'blah'}????
next();
});
how do i get the update query of {set:{a:'blah'}} in the pre middleware so i can do some checks before executing the update?
alternatively i know that the update query can be accessed in the post middleware, in
schema.post('update',function(){
var findQuery=this._conditions; // gives {_id:'blah'}
var updateQuery=this._update; //gives {$set:{a:'blah'}}
next();
});
but thats too late, i need this in the pre middleware to check before actually updating the db.
i tried looking through the 'this' object of the pre middleware but cannot find the updateQuery object anywhere and this._update is undefined in the pre middleware.
Is there a way to do this?
thanks
In case you're still looking for a solution that works on array operations, it looks like in newer versions of mongoose (at least 4.0.7+), this._update is defined in the pre-middleware.
I found a work around through this particular example, however it doesnt quite solve my actual problem. what you can do in mongoose version ~4.0.0 is to let the pre middleware specify to go through the model validation on update.
schema.pre('update',function(next){
this.options.runValidators = true; // make sure any changes adhere to schema
})
basically, you can then specify the validators inside the schema
var schema = new Schema({
a:{
type:String,
validate:[...] //the validation you want to run
}
});
you can choose to skip the validation on a normal save operation by using the this.isNew check inside validation functions.
this code will run validate:[...] on any $set and $unset to a in your update query.
however, it doesn't work on array operations like $push or $addToSet for some reason. so if your updating an array, it won't run the validation code at all! hence it doesn't solve the actual problem im faced with. but it can work with the example provided for anyone that comes across this particular problem

Mongo Database Fixing Names after Mongoose Index?

I had a very weird issue with the way Mongoose interacted with my Node and Mongo database.
I was using express to create a basic get api route to fetch some data from my mongodb.
I had a database called test and it had a collection call "billings"
so the schema and route was pretty basic
apiRouter.route('/billing/')
.get(function(req, res) {
Billing.find(function(err, billings) {
if (err) res.send(err);
// return the bills
res.json(billings);
});
});
Where "Billing" was my mongoose schema. that simply had 1 object {test: string}
This worked fine, I got a response with all the items in my mongo db called "billings" which is only one item {test: "success"}
Next I created a collection called "historys"
I setup the exact same setup as my billings.
apiRouter.route('/historys/')
// get all the history
.get(function(req, res) {
Historys.find(function(err, historys) {
if (err) res.send(err);
// return the history
res.json(historys);
});
});
where again "Historys" was my mongoose schema. This schema was identical in setup to my billings since I didnt have any real data, the fields were the same, i just had it with a test field so the json object returned from both billings and historys should have been
{ test: "success" }
However, this time I didnt get any data back, I just got an empty object
[].
I went through my code multiple times to make sure maybe a capital got lost, or a comma somewhere etc, but the code was identical. the setup and formatting in my mongodb was identical. I went into robomongo and viewed the database and everything was named correctly.
Except, I had 2 new collections now.
My original : "Historys" AND a brand new collection "Histories"
Once i fixed my api route to go look at Histories instead of Historys, I was able to get the test data successfully. I still however cannot pull data from Historys, its like it doesnt exist yet there it was in my robomongo console when I refreshed.
I searched all my code for any mention of histories and got 0 results. Where did the system know to fix the grammar on my collection?
From the docs:
When no collection argument is passed, Mongoose produces a collection name by passing the model name to the utils.toCollectionName method. This method pluralizes the name. If you don't like this behavior, either pass a collection name or set your schemas collection name option.
So, when you did, in your schema definition, this:
mongoose.model('Historys', YourSchema);
, mongoose created the Histories collection.
When you do:
db.historys.insert({ test: "success" })
through mongodb console, if the historys collection doesn't exist, it'll be created. That's why you have the two collections in your db. Like the docs said, if you don't want mongoose to create a collection with a pluralized name based on your model, just specify the name you want.

Populate doesn't work Mongoose (no database insertion)

I've got a big problem, i'm trying to use model associations in Mongoose because it would be really useful but there's something i don't get ...
Let's say there's a User model with a schema like ... (among others)
user_geos : [{
type: Mongo.Schema.ObjectId,
ref: 'UserGeo',
}]
And there's a UserGeo model with this schema ... (among others)
_user: {
type: Mongo.Schema.ObjectId,
ref: 'User'
}
Very simple, when I'm creating a new UserGeo, it should automatically add it to the user_geos array within User, right ?
user_geo_infos._user = user.id;
db.UserGeo.create(user_geo_infos, function(error, user_geo) {
catches.error(error);
console.log(user_geo);
});
The big problem I got is when i'm creating it, it fills correctly the "_user" field in UserGeo in the database but the User model doesn't fill itself. The array stay empty ("[]"). A detail but you really understood is UserGeo got one User and User got many UserGeo.
I'm really stuck, did i do something wrong ? I checked everywhere and read the Mongoose documentation like 10 times now ...
Any idea ? Thanks people ;)
Very simple, when I'm creating a new UserGeo, it should automatically add it to the user_geos array within User, right ?
Nope. There is a lot less magic/automatic stuff here than you are hoping for. Mongodb, as well as mongoose, will only ever act upon a single collection at a time. This will do the querying automatically when you load records and use the mongoose .populate helper, but it doesn't help you writing across collections.
Ok I tried to make it manually and it works but i'm quite disappointed ... Looks like this ...
db.UserGeo.create(user_geo_infos, function(error, user_geo) {
db.User.findOne(user.id, function(error, user) {
catches.error(error);
user.user_geos.push(user_geo.id);
user.save();
});
catches.error(error);
console.log(user_geo);
});
After I create a UserGeo I get the User and then push the new data to the User field ...
This is solution is heavy, maybe make some helpers would make it lighter .. Thanks anyway :)

Resources