[SERVER-27902] mongoDB Validations: How to apply mongoDB validation for Multiple elements of json of Array. Created: 03/Feb/17  Updated: 04/Feb/17  Resolved: 04/Feb/17

Status: Closed
Project: Core Server
Component/s: Storage
Affects Version/s: None
Fix Version/s: None

Type: Question Priority: Major - P3
Reporter: monika Assignee: Kelsey Schubert
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Participants:

 Description   

Hi Team,

I might have posted the question with incorrect components or may be project. But the question is regarding validation feature in mongoDB. Please help me on it.

Question:
If I enable mongoDB validation using mongoShell for json of array element then the validation works only if I pass one element as json in the array. However if I pass multiple elements in array for insert/update then validation do not work properly, In this case invalid data is also allowed.

I have done rigorous search about it and could not find anything helpful.

Please let me know how to apply validation for multiple elements for array of json for insert/update. Validation is a great feature in mongoDB and I would like to keep it using.

Thanks.



 Comments   
Comment by Kelsey Schubert [ 04/Feb/17 ]

Hi monika123,

Thanks for clarifying what you're trying to do. To achieve the desired functionality, please use $elemMatch.

Specifically, I believe the following works for your use-case:

db.runCommand({
    collMod: "test",
    validator: {
        "testId": {"$exists": true},
        "$and": [
            {"$or": [
                {"createdAt": {"$exists": true, "$type": "long"}}, 
                {"createdAt": {"$exists": false}}
            ]},
            {"$or": [
                {
                    "testSettings": {
                        "$exists": false
                    }
                },
                {
                "testSettings" : 
                    {"$not" :
                        {"$elemMatch" : 
                            {"$or": [
                                {"name": {"$exists": false}}, 
                                {"vlanId": {"$exists": false}}
                            ]
                        }
                        }
                    }
                }               
            ]}
        ]
    }
})

Please note that SERVER project is for reporting bugs or feature suggestions for the MongoDB server. For MongoDB-related support discussion please post on the mongodb-user group or Stack Overflow with the mongodb tag. A question like this involving more discussion would be best posted on the mongodb-users group.

Kind regards,
Thomas

Comment by monika [ 04/Feb/17 ]

Hi Thomas,
I am using MongoDB version "3.2.11".

Below are the steps that will help you understand my issue:-

Step 1- Created a collection 'test'

db.createCollection('test')

Step 2- Applied Validations on the 'test' collection to implement the following checks-

  • key 'testId' should be mandatory in the document to be inserted (Not null).
  • key 'createdAt' should contain a 'long' datatype value if present.
  • key 'testSettings' is an array which must contain two keys 'name' and 'vlanId'.

    db.runCommand({
    collMod: "test",
    validator: {
    testId: {$exists:true},
    $and:[
    {$or:[{"createdAt": {$exists:true,$type:"long"}}, {"createdAt": {$exists:false}}]},
    { $or: [
            {
                "testSettings": {
                    $exists: false
                }
            },
            {
                $and: [
    						{"testSettings.name": {$exists:true}},
    						{"testSettings.vlanId": {$exists:true}}
                    		
                       ]
    		}
    ]}
    ]}
    })
    

    Step 3:- (CASE 1) Inserted the below record in test collection in which key 'vlanId' is not present. Got 'document failed validation' error which is logically perfect.

    db.test.insert({
        testId:"2",
        createdAt:NumberLong("1234567"),
        testSettings:[
                    {
                        name:"test record2"
                     }
                ]
        })
    

    Output-

    WriteResult({
    	"nInserted" : 0,
    	"writeError" : {
    		"code" : 121,
    		"errmsg" : "Document failed validation"
    	}
    })
    

    Step 4:- (CASE 2) Inserted the below record in 'test' collection where array 'testSettings' contains two JSON objects in which first element contains both mandatory keys while in the second element key 'vlanId' is missing (mandatory key). But, record inserted successfully.

    db.test.insert({
        testId:"1",
        createdAt:NumberLong("123456"),
        testSettings:[
                    {
                        name:"test record1",
                        vlanId:"v1"
                     },
                      {
                        name:"test record2"
                     }
                ]
        })
    

    output:

    WriteResult({ "nInserted" : 1 })
    

    So, here comes my issue that in MongoDB validation checks got satisfied when at least one element of array fulfilled the validation checks. Why?? Are validations for nested arrays not possible in MongoDB?

Thanks

Comment by Kelsey Schubert [ 03/Feb/17 ]

Hi monika123,

I just did quick check with MongoDB 3.4.1 and was unable to reproduce the behavior you describe. Would you please clarify which version of MongoDB you are using, and provide steps to reproduce?

> db.createCollection("foo", {validator: {x :{$exists:true}})}
{ "ok" : 1 }
> db.foo.insert([{},{}])
BulkWriteResult({
	"writeErrors" : [
		{
			"index" : 0,
			"code" : 121,
			"errmsg" : "Document failed validation",
			"op" : {
				"_id" : ObjectId("589472bb8c8fe8c3529cdef0")
			}
		}
	],
	"writeConcernErrors" : [ ],
	"nInserted" : 0,
	"nUpserted" : 0,
	"nMatched" : 0,
	"nModified" : 0,
	"nRemoved" : 0,
	"upserted" : [ ]
})
> db.foo.find()
{ "_id" : ObjectId("5894728c8c8fe8c3529cdeef"), "x" : 1 }
> db.foo.insert([{x:1},{}])
BulkWriteResult({
	"writeErrors" : [
		{
			"index" : 1,
			"code" : 121,
			"errmsg" : "Document failed validation",
			"op" : {
				"_id" : ObjectId("589472c88c8fe8c3529cdef3")
			}
		}
	],
	"writeConcernErrors" : [ ],
	"nInserted" : 1,
	"nUpserted" : 0,
	"nMatched" : 0,
	"nModified" : 0,
	"nRemoved" : 0,
	"upserted" : [ ]
})
> db.foo.find()
{ "_id" : ObjectId("589472c88c8fe8c3529cdef2"), "x" : 1 }

Thank you,
Thomas

Generated at Thu Feb 08 04:16:34 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.