1

I want to toggle the boolean value which is in the array of the schema. I am trying to toggle the value with the value present in the database(refer the code). But it is just turning true to false, but not false to true.

Following is the code

exports.postStatusItemchange = (req, res, next) => {
  const productId = req.body.productId;
  const itemId = req.body.itemId;
  
  Product.updateOne({_id: productId, "items._id": itemId}, {
    $set: {
      "items.$.status": !"items.$.status"
    }
  }).then((result) => {
    console.log(result);
    res.send("done");
  }).catch(err => {
    res.send(err);
  })
}

Following is the schema for the reference

const productSchema = new Schema({
  name: {
    type: String,
    required: false,
  },
  status: {
    type: Boolean,
    required: false,
    default: true,
  },
  items: [
    {
      foodName: {
        type: String,
        required: true,
      },
      price: {
        type: Number,
        required: true,
      },
      status: {
        type: Boolean,
        default: true
      }
    },
  ],
});

I am expecting that the value in the status field gets toggle whenever the API is ran. Thank you for your time.

cmgchess
  • 7,996
  • 37
  • 44
  • 62
Krish
  • 53
  • 1
  • 6

1 Answers1

1

unfortunately, the positional operators won't be much of help in this case and you will have to go for something hectic with map. This has its disadvantages since it has to loop over every item in the items array. Also, note that I'm using [{$set:{...}}] that's because from Mongo 4.2 onwards you can aggregation pipeline inside update.

Product.updateOne({_id: productId}, 
[
  {
    $set: {
      items: {
        $map: {
          input: "$items",
          as: "i",
          in: {
            $cond: [
              { $eq: [ "$$i._id", itemId ] },
              { $mergeObjects: [ "$$i", { status: { $not: "$$i.status" } } ] },
              "$$i"
            ]
          }
        }
      }
    }
  }
]
)

playground

This is what I meant. You need to pass an explicit value if you are going to use $set with positional operators. Otherwise, even if you write a condition it will update the field with the whatever condition object passed.

cmgchess
  • 7,996
  • 37
  • 44
  • 62