Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Version error on saving Mongoose docs

I have an issue - not sure if I am doing something wrong or it's a bug. I have some products - each of these has an array of variations. I want to go through some data and load it in these variations but I experience a number of 'VersionError: No matching document found' errors.

Thinking I was having a race condition (I am sequenctially saving the same document for each of its variations that I modify) I used asyc.eachSeries() but that did not help. Loading the error causing documents one at the time does not yield the error so it seems related to some race condition but I cannot track it down.

Schema:

var Product = new Schema({
  title: {
    type: String,
  },  
  variations: {
    type: Array
  }
});

Sample code:

// Some data to load - the 'variant' is the index of the variations array above
var records = [{
  code: 'foo',
  id: '50ba9c647abe1789f7000073',
  variant: 0
}, {
  code: 'bar',
  id: '50ba9c647abe1789f7000073',
  variant: 1
}, {
  code: 'foobar',
  id: '50ba9c647abe1789f7000073',
  variant: 2
}];

var iterator = function(item, cb) {
  Product.findById(item.id).exec(function(err, product) {
    if(err) {
      return cb(err);
    }
    if (product) {
      product.variations[item.variant].code = item.code.trim();
      product.markModified('variations');
      product.save(function(err, p) {
        return cb(err);
      });
    } else {
      return cb('Missing product');
    }
  });
};

async.eachSeries(records, iterator, function(err) {
  process.exit(1);
});
like image 222
cyberwombat Avatar asked Nov 01 '22 08:11

cyberwombat


2 Answers

I think the problem is how you've defined your schema. It's much to better to have variant be it's own schema and have the product schema use that as a sub doc instead. I would change it to look something like this:

var Variant = new Schema({
    code: String,
})

var Product = new Schema({
    title: String,
    variants: [Variant]
})

Then you could go through the records like so:

var variants = product.variants
for (i in variants) {
    var variant = variants[i]
    variant.code = records[i].code
    variant.save(function(err) {
        ...
    })
}
like image 197
Mattias Farnemyhr Avatar answered Nov 12 '22 20:11

Mattias Farnemyhr


If in model Scheme you using versionKey the problem can come when, doc called from mongo multiple times, In that case the best way is send all object of doc, near example

function getDoc(doc, callback) {
    if ( doc instanceof Object && doc._id ) {
        callback(null, doc);
    } else {
        return Doc.findById(doc, callback);
    }
}

function updateDoc(doc, data) {
   // doc is already model
   getDoc(doc, function(err, doc) {
       doc.data = data;
       doc.save();
   });
}
like image 28
Vahan Gevorgyan Avatar answered Nov 12 '22 19:11

Vahan Gevorgyan