Bhoomika Chauhan
Bhoomika Chauhan

Reputation: 153

Mongoose findByIdAndUpdate method to toggle and update a Boolean value in database

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

Answers (5)

user21520002
user21520002

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

Wollaspta
Wollaspta

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:

  • Method Override.
  • Body Parser.

Upvotes: -1

Cl&#233;ment E.
Cl&#233;ment E.

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

slugonamission
slugonamission

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

Austin Ezell
Austin Ezell

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

Related Questions