0
votes

I am creating a user experience where a user will be able to rate items from different vendors. My initial thought is for each User schema to have an array which stores all the items that the user has rated. The rated item would include the unique vendor item ID and a numerical rating value.

User Model

const userSchema = new mongoose.Schema({
  ...
  userType: String,
  ratedItems: Array,
  ...
});

Controller

exports.postUpdateRatedItem = (req, res, next) => {
  User.findById(req.user.id,  (err, user) => {
    if (err) { return next(err); }
    user.update(
      { $push: {ratedItems : {
        vendorItem : req.body.itemID,
        rating : req.body.rating
      }}},

      function (err) {
        res.send(200);
    });

  });
}

Current Output

{ 
  "_id" : ObjectId("5c91869a71ece20551fd6aed"),
  "userType" : "participant",
  "ratedItems" : [ 
    { "vendorItem" : "5c9bdd524a0dfa753e08a0a4", "rating" : "3" },
    { "vendorItem" : "5c9bdd524a0dfa753e08a0a4", "rating" : "6" }
  ]
}

This approach works great in adding new object to the array, but only adds and does not update. Instead, every time a user updates a rating, a new object is added to the array. What approach would allow to check for the unique vendorItem id? How do I go about checking the user rated items? If found, update the rating value, if not found, push to the array.

Thank you in advance, still learning MongoDB/Mongoose.

Edit

Below is what I expect the outcome. For each object in the array, the 'rating' is updated when the user changes the rating. The ratedItems array will eventually have many many vendorItem with unique IDs and ratings.

Expected Output

{ 
  "_id" : ObjectId("5c91869a71ece20551fd6aed"),
  "userType" : "participant",
  "ratedItems" : [ 
    { "vendorItem" : "5c9bdd524a0dfa753e08a0a4", "rating" : "6" },
    // additional rated items all with unique IDs
    { "vendorItem" : "5c9bcc14d5161c38a4581e28", "rating" : "2" },
    { "vendorItem" : "5c9407d143cd0f20d758acdb", "rating" : "11" }

  ]
}
1

1 Answers

0
votes

It sounds like you are looking for "upsert" functionality. The Mongoose model API provides findByIdAndUpdate and other similar methods for this.

Make sure you set the new and upsert options to true. This will create the object if it doesn't exist and return the modified document if it is updated.

Your use case would look something like this:

const update = {
  $push: {
    ratedItems: {
      vendorItem: req.body.itemID,
      rating: req.body.rating
    }
  }
};

const options = {'new': true, upsert: true};

User.findByIdAndUpdate(req.user.id, update, options, function(err, user) {
  // ...
});