Reputation: 153
I'm trying to toggle and update a boolean value in database whenever a button is clicked..
My HTML:
<form action="/browse/<%= book._id %>/sold" method="GET">
<button type="submit"> Mark As Sold </button>
</form>
Schema:
var bookSchema = new mongoose.Schema({
title: String,
description: String,
sold: { type:Boolean, default: false }
});
I've tried to use this on the .get route :
Book.findByIdAndUpdate(req.params.id, {$set: {sold: !sold} }, function(err, book){
....
}
but it doesnt work.. (sold is undefined)
I'm new to express and mongoose and searched on google a lot but couldnt find a solution. Please help. is there any other way to solve this?
Upvotes: 4
Views: 11663
Reputation: 1
You can base it on $mod
judging odd and even numbers
$mod : [2,0]
$mod : [2,1]
var bookSchema = new mongoose.Schema({
title: String,
description: String,
sold: { type:Number, default: 0 }
});
bookSchema.findOneAndUpdate({_id:req.params.id},{$inc:{sold: 1}});
bookSchema.findOne({_id:req.params.id, sold:{$mod : [2,0]}})
Upvotes: 0
Reputation: 1
app.put("/todo/update/:id", function (req, res) {
Todo.findById(req.params.id, function (err, todo) {
todo.done = !todo.done;
todo.save(function (err, updatedTodo) {
if (err) {
console.log(err);
} else {
res.redirect("/")
}
})
})
});
This is an example I used using the express, mongoose and nodejs.
Here is an example of my model:
const todoSchema = new mongoose.Schema({
text: {
type: String,
required: true
},
done: {
type: Boolean,
default: false
}
});
const Todo = mongoose.model('Todo', todoSchema);
Other Dependencies:
Upvotes: -1
Reputation: 61
You could just update the document in this convenient way :
Book.findOne({ _id: req.params.id }, function(err, book) {
book.sold = !book.sold;
book.save(function(err, updatedBook) {
...
});
});
Upvotes: 5
Reputation: 9632
There's sadly no way to directly invert a record in a single operation - if you want to operate on just booleans, you need to find, mutate, then save again as Austin says.
If you can change your data slightly though, we can actually approximate this using integers. If we use integers, we can use bitwise operations to do this, e.g.
Book.insert({myBoolVal: 0}); // Insert as false
Book.findAndUpdate(req.params.id, {$bit: {myBoolVal: {xor: 1}}}); // 0 xor 1 = 1; 1 xor 1 = 0
Book.find({myBoolVal: 0}); // false
Book.find({myBoolVal: 1}); // true
In this case, your Mongoose model must specify myBoolVal
to be an integer. This requires the Int32
package, as of this answer: Mongoose ODM: NumberInt is not defined. For example:
var NumberInt = require("mongoose-int32");
var bookSchema = new mongoose.Schema({
title: String,
description: String,
sold: { NumberInt, default: 0}
});
Upvotes: 5
Reputation: 763
The method you are using will not work. You are referencing an undeclared
variable sold
in this snip: {sold: !sold}
. If anything, you'd want to do {sold: !this.sold}
, but this
within a findById
is a query and not the model. You would have to use findById
for the book you want, update it manually (book.sold = !book.sold
) then save
it.
You could create a static method on your model to accomplish all this.
It would look something like
bookSchema.statics.findByIdAndToggleSold = function(id, callback){
// Your code to find, then update here.
}
Upvotes: 9