CampbellSoftwareSolutions / mongoose-id-validator

Mongoose plug in to validate ObjectID references point to valid existing documents.
Other
47 stars 26 forks source link

Duplicated ObjectID in the array cannot pass the validation #12

Closed allientneko closed 8 years ago

allientneko commented 8 years ago

I'm using v0.1.10 in my project,

Here is my code: var playerSchema = new Schema({ weapon: { type: ObjectId, ref: 'Weapons' }, items: [{ type: ObjectId, ref: 'Items' }] }); playerSchema.plugin(idValidator);

I put two items in the items list:

player.items = [ '56c3236161cc8225002df141', '56c3236161cc8225002df141' ]

when I try to save this player. The backend told me that one ID in player.items is non-exist. I am 100% sure 56c3236161cc8225002df141 is in my items collection.

I trace down the problem: function validateIdArray(doc, connection, refModelName, values, conditions, respond) { if (values == null || values.length == 0) { return respond(true); } var refModel = connection.model(refModelName); var query = refModel.count().where('_id')['in'](values); executeQuery(query, conditions, values.length, respond); }

The problem should be here. executeQuery(query, conditions, values.length, respond); values.length in my case is 2.

Inside the function: function executeQuery(query, conditions, validateValue, respond) { for (var fieldName in conditions) { query.where(fieldName, conditions[fieldName]); } query.exec(function (err, count) { if (err) { return respond(err); } respond(count === validateValue); }); }

respond(count === validateValue);

However, count is only 1 if the array contain 2 same ObjectId.

I try to modified the code: `function validateIdArray(doc, connection, refModelName, values, conditions, respond) { if (values == null || values.length == 0) { return respond(true); } var refModel = connection.model(refModelName);

var unique = function(arr) {
  var n = {},r=[];
  for(var i = 0; i < arr.length; i++)  {
     if (!n[arr[i]]) {
         n[arr[i]] = true; 
        r.push(arr[i]); 
    }
}
return r;
}

var uniqueValues = unique(values);
var query = refModel.count().where('_id')['in'](uniqueValues);
executeQuery(query, conditions, uniqueValues.length, respond);

}`

Then it works as normal. I guess the biggest problem is duplicate ObjectId in the same array.

martin-css commented 8 years ago

Thanks for reporting your issue. The original validator was never intended to handle duplicate ID references in an array of references.

I've amended the library to support this. If you set the allowDuplicates option to true then any array of ID references containing duplicates should validate successfully.

I've not set this as a default option at the moment as this may not be intuitively expected functionality. It's possible that someone might accidentally insert duplicate entries into an array.

If the community consensus is such that this should be default functionality then it can be changed in the future.