Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-31402

Document validator fails to reject invalid values in array member

    XMLWordPrintable

    Details

    • Operating System:
      ALL
    • Steps To Reproduce:
      Hide

      > db.createCollection('testio', {
      ...   validator: { $or: [
      ...     { dbRefsMember: { $exists: false } },
      ...     {
      ...       $and: [
      ...         { dbRefsMember: { $type: 'object' } },
      ...         { 'dbRefsMember._id': { $exists: false } }
      ...       ]
      ...     }
      ...   ] }
      ... });
      { "ok" : 1 }
      > db.testio.insert({existsFalseValidatesThis:'asItShould'})
      WriteResult({ "nInserted" : 1 })
      > db.testio.insert({dbRefsMember:[{_id: 1, thisGuy: 'shouldAndWillBeRejected'}]})
      WriteResult({
      	"nInserted" : 0,
      	"writeError" : {
      		"code" : 121,
      		"errmsg" : "Document failed validation"
      	}
      })
      > db.testio.insert({dbRefsMember:[false, {_id: 1, thisGuy: 'shouldAndWillAlsoBeRejected'}]})
      WriteResult({
      	"nInserted" : 0,
      	"writeError" : {
      		"code" : 121,
      		"errmsg" : "Document failed validation"
      	}
      })
      > db.testio.insert({dbRefsMember:[1, {thisGuy: 'shouldButWillNotBeRejected'}]})
      WriteResult({ "nInserted" : 1 })
      > db.testio.insert({more:1})
      WriteResult({ "nInserted" : 1 })
      > db.testio.update({more:1}, {$set: {dbRefsMember: []}})
      WriteResult({
      	"nMatched" : 0,
      	"nUpserted" : 0,
      	"nModified" : 0,
      	"writeError" : {
      		"code" : 121,
      		"errmsg" : "Document failed validation"
      	}
      })
      > db.testio.update({more:1}, {$set: {dbRefsMember: [1]}})
      WriteResult({
      	"nMatched" : 0,
      	"nUpserted" : 0,
      	"nModified" : 0,
      	"writeError" : {
      		"code" : 121,
      		"errmsg" : "Document failed validation"
      	}
      })
      > db.testio.update({more:1}, {$set: {dbRefsMember: [DBRef('something', ObjectId())]}})
      WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
      > db.testio.update({more:1}, {$push: {dbRefsMember: 1}})
      WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
      > db.testio.update({more:1}, {$push: {dbRefsMember: false}})
      WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
      > db.testio.update({more:1}, {$push: {dbRefsMember: {_id: 'anotherViolationButThisTimeNotOnTheType'}}})
      WriteResult({
      	"nMatched" : 0,
      	"nUpserted" : 0,
      	"nModified" : 0,
      	"writeError" : {
      		"code" : 121,
      		"errmsg" : "Document failed validation"
      	}
      })
      > db.testio.findOne({more:1})
      {
      	"_id" : ObjectId("59d63137f402d1a9c67ea8ef"),
      	"more" : 1,
      	"dbRefsMember" : [
      		DBRef("something", ObjectId("59d63164f402d1a9c67ea8f0")),
      		1,
      		false
      	]
      }
      > db.testio.insert({more:2}, {$set: {dbRefsMember: [1,2,3,false,'aString',DBRef('something', ObjectId())]}})
      WriteResult({ "nInserted" : 1 })
      

      Show
      > db.createCollection( 'testio' , { ... validator: { $or: [ ... { dbRefsMember: { $exists: false } }, ... { ... $and: [ ... { dbRefsMember: { $type: 'object' } }, ... { 'dbRefsMember._id' : { $exists: false } } ... ] ... } ... ] } ... }); { "ok" : 1 } > db.testio.insert({existsFalseValidatesThis: 'asItShould' }) WriteResult({ "nInserted" : 1 }) > db.testio.insert({dbRefsMember:[{_id: 1, thisGuy: 'shouldAndWillBeRejected' }]}) WriteResult({ "nInserted" : 0, "writeError" : { "code" : 121, "errmsg" : "Document failed validation" } }) > db.testio.insert({dbRefsMember:[ false , {_id: 1, thisGuy: 'shouldAndWillAlsoBeRejected' }]}) WriteResult({ "nInserted" : 0, "writeError" : { "code" : 121, "errmsg" : "Document failed validation" } }) > db.testio.insert({dbRefsMember:[1, {thisGuy: 'shouldButWillNotBeRejected' }]}) WriteResult({ "nInserted" : 1 }) > db.testio.insert({more:1}) WriteResult({ "nInserted" : 1 }) > db.testio.update({more:1}, {$set: {dbRefsMember: []}}) WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0, "writeError" : { "code" : 121, "errmsg" : "Document failed validation" } }) > db.testio.update({more:1}, {$set: {dbRefsMember: [1]}}) WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0, "writeError" : { "code" : 121, "errmsg" : "Document failed validation" } }) > db.testio.update({more:1}, {$set: {dbRefsMember: [DBRef( 'something' , ObjectId())]}}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.testio.update({more:1}, {$push: {dbRefsMember: 1}}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.testio.update({more:1}, {$push: {dbRefsMember: false }}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.testio.update({more:1}, {$push: {dbRefsMember: {_id: 'anotherViolationButThisTimeNotOnTheType' }}}) WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0, "writeError" : { "code" : 121, "errmsg" : "Document failed validation" } }) > db.testio.findOne({more:1}) { "_id" : ObjectId( "59d63137f402d1a9c67ea8ef" ), "more" : 1, "dbRefsMember" : [ DBRef( "something" , ObjectId( "59d63164f402d1a9c67ea8f0" )), 1, false ] } > db.testio.insert({more:2}, {$set: {dbRefsMember: [1,2,3, false , 'aString' ,DBRef( 'something' , ObjectId())]}}) WriteResult({ "nInserted" : 1 })

      Description

      Hi

      I was trying to add document validation to avoid an issue with our software where a document, containing an array of DBRefs was saved back with those DBRefs resolved to their foreign documents. In other words, to validate that the items in this array member are indeed DBRefs.

      As DBRef is not available as a $type to check against, I had to get creative and instead opted for this not-exactly-foolprof idea: Either, the member must not exist, or it must be an array of objects which does not have an _id property.

      In my testing, it becomes clear that it stops rejecting invalid updates once the array contains one valid member. In essence, the validator seems to say, "yep, everything okay" so long as the validator rule, if used as a query, would yield the document being validated.

      I don't see this behavior mentioned anywhere in the docs, so I'm thinking it's a bug. Please see my steps to reproduce for clarification.

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              Unassigned Unassigned
              Reporter:
              Daniel Smedegaard Buus Daniel Smedegaard Buus [X]
              Participants:
              Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: