26

I have some problem when I try to upsert my object with new ones(parsed from xml file),but I got the following error:

 MongoError: exception: After applying the update to the document {_id: ObjectId('55be3c8f79bae4f80c6b17f8') , ...}, the (immutable) field '_id' was found to have been altered to _id: ObjectId('55be5f15ae
5597401724aab3')

Here is my code:

xmlFile.product_list.product.forEach(function (product) {

                    var productEntity = new Product({
                        product_id: parseInt(product.id),
                        parent_id: parseInt(product.parent_id),
                        sku: product.sku,
                        title: product.title,
                        pricenormal: parseFloat(product.price_normal),
                        pricewholesale: parseFloat(product.price_wholesale),
                        pricewholesalelarge: parseFloat(product.price_wholesale_large),
                        pricesale: parseFloat(product.price_sale),
                        weight: parseFloat(product.weight),
                        volume: parseFloat(product.volume),
                        unittype: product.unit_type,
                        status: product.status,
                        datecreating: product.datecreating,
                        sp: product.sp,
                        guaranteeext: product.guarantee_ext,
                        used: product.used,
                        statusfull: product.status_full,
                        description: null,
                        url: null
                    });
                    items.push(productEntity);

                });


items.forEach(function (product) { //update or create new products

                    Product.findOneAndUpdate({product_id: product.product_id}, product, {upsert: true}, function (err) {
                        if (err)  return updateDBCallback(err);
                        updateDBCallback(null, 'saved');

                    });

                });

I tried to use hints like:

                //product._id = mongoose.Types.ObjectId(); //doesn't work
                //delete product._id // doesn't delete _id from product

but they didn't help. So I don't want to update my product._id , I just want to update the other fields.

Wandering Fool
  • 2,170
  • 3
  • 18
  • 48
MeetJoeBlack
  • 2,804
  • 9
  • 40
  • 66

5 Answers5

32

When you do new Product(), a new _id is generated, along with other things. Try this:

items.forEach(function (product) { //update or create new products

  // Es6 assign
  var productToUpdate = {};
  productToUpdate = Object.assign(productToUpdate, product._doc);
  delete productToUpdate._id;

  Product.findOneAndUpdate({product_id: product.product_id}, productToUpdate, 
                         {upsert: true}, function (err) {
    if (err)  return updateDBCallback(err);
       updateDBCallback(null, 'saved');

  });

});
Alfonso Embid-Desmet
  • 3,561
  • 3
  • 32
  • 45
  • 1
    When I tried to use Object.assign with node v0.12.7 I got 'TypeError: undefined is not a function', so I had to use this shim https://www.npmjs.com/package/object-assign – wytten Nov 30 '15 at 21:34
  • For typescript users: `Any property declared with let or const cannot be deleted from the scope within which they were defined.` https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete – Janac Meena May 29 '18 at 15:47
  • I am getting this error `obj.toObject is not a function` – Al Fahad Apr 16 '20 at 05:45
3

You can use this:

Product.replaceOne({ _id: 55be3c8f79bae4f80c6b17f8}, {                         
   product_id: parseInt(product.id),
   parent_id: parseInt(product.parent_id),
   sku: product.sku,
   title: product.title,
   pricenormal: parseFloat(product.price_normal),
   pricewholesale: parseFloat(product.price_wholesale),
   pricewholesalelarge: parseFloat(product.price_wholesale_large),
   pricesale: parseFloat(product.price_sale),
   weight: parseFloat(product.weight),
   volume: parseFloat(product.volume),
   unittype: product.unit_type,
   status: product.status,
   datecreating: product.datecreating,
   sp: product.sp,
   guaranteeext: product.guarantee_ext,
   used: product.used,
   statusfull: product.status_full,
   description: null,
   url: null});
Emma
  • 27,428
  • 11
  • 44
  • 69
Bharath T
  • 31
  • 1
3

try to use

const product = productEntity.toObject();
...
delete product._id;
...
Product.findOneAndUpdate({product_id: product.product_id}, product)
thomas
  • 31
  • 1
  • While this code may resolve the OP's issue, it is best to include an explanation as to how your code addresses the OP's issue. In this way, future visitors can learn from your post, and apply it to their own code. SO is not a coding service, but a resource for knowledge. Also, high quality, complete answers are more likely to be upvoted. These features, along with the requirement that all posts are self-contained, are some of the strengths of SO as a platform, that differentiates it from forums. You can edit to add additional info &/or to supplement your explanations with source documentation. – ysf Jun 17 '20 at 18:37
1

I got this error (in the Java driver) when my check for an _id was a String instead of an ObjectId.

Wrap your query appropriately:

myCoolCollection.findOneAndUpdate(Filters.eq("_id", new ObjectId(e.id)), ...
Robert
  • 1,220
  • 16
  • 19
0

C# / .Net

If you are using _user.ReplaceOneAsync(user => user.Id == id, userIn) to update an existing record in the collection then make sure to include the id of the actual record which are updating, leaving it blank means you want it to generate the newGuid for you when it create the new instance of the class.

 public class User
 {
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public string Id { get; set; }
 }

var userCollection = await _claim.FindAsync(user => user.Id == id);
var userToUpdate = userCollection.FirstOrDefault();

//if user exists then provide the same id(primary key) to update the record
User updateUser = new User
{
     Id = userToUpdate.id,   // same id if the class creates one if you dont provide one.
     UserId = "000ef15d8c1ee9cd62699999",
     Email = "email",
}

wait _user.ReplaceOneAsync(user => user.Id == id, updateUser);
Si Zi
  • 1,109
  • 10
  • 6