{"id":103514,"date":"2024-09-13T20:39:26","date_gmt":"2024-09-13T20:39:26","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=103514"},"modified":"2024-11-14T22:03:29","modified_gmt":"2024-11-14T22:03:29","slug":"working-with-schema-validation-in-mongodb","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/databases\/nosql\/mongodb\/working-with-schema-validation-in-mongodb\/","title":{"rendered":"Working with Schema Validation in MongoDB"},"content":{"rendered":"<p><strong>This article is part of Robert Sheldon's continuing series on Mongo DB. To see all of the items in the series, <a href=\"https:\/\/www.red-gate.com\/simple-talk\/collections\/robert-sheldon-ongoing-mongodb-primer\/\">click here<\/a>.<\/strong><\/p>\n\n<p>In the previous article in this series, I introduced you to schema validation in MongoDB. I described how you can define validation rules on a collection and how those rules validate document inserts and updates. In this article, I continue the discussion by explaining how to apply validation rules to documents that already exist in a collection. Before you start in on this article, however, I recommend that you first review the previous article for an introduction into schema validation.<\/p>\n<p>The examples in this article demonstrate various concepts for working with schema validation, as it applies to existing documents. I show you how to find documents that conform and don\u2019t conform to the validation rules, as well as how to bypass schema validation when inserting or updating a document. I also show you how to update and delete invalid documents in a collection. Finally, I explain how you can use validation options to override the default schema validation behavior when inserting and updating documents.<\/p>\n<p>Note: For the examples in this article, I used the same MongoDB Atlas and MongoDB Compass environments I used for the previous articles in this series. Refer to the first article for details about setting up these environments. Because this article builds off the previous article, I\u2019ve also used the same <code>hr<\/code> database and <code>candidates<\/code> collection for the examples. If you\u2019ve already deleted the database and collection, you can simply re-create them. The goal is to start with an empty collection with no validation rules defined.<\/p>\n<h2>Searching for invalid documents in a MongoDB collection<\/h2>\n<p>When you define schema validation rules on a collection that already contains documents, some of those documents might not adhere to the new rules. In which case, you might want to search your collection to determine which documents conform to the rules and which ones do not.<\/p>\n<p>In this section, I demonstrate how to find valid and invalid documents. If you want to try out the examples, you should create the <code>hr<\/code> database and <code>candidates<\/code> collection, if they don\u2019t already exist.<\/p>\n<p>The examples in this article were developed for MongoDB Shell. You can use the version of Shell integrated into MongoDB Compass, or you can use the version available through your system\u2019s command-line utility. I like using the version in Compass because I can quickly review my inserted and updated documents.<\/p>\n<p>If your collection contains any documents, delete those and then delete any validation rules. To remove validation rules, open MongoDB Shell, switch to the <code>hr<\/code> database, and run the following <code>runCommand<\/code> statement:<\/p>\n<pre class=\"lang:none theme:none\">db.runCommand( { collMod: \"candidates\", validator: {} } );<\/pre>\n<p>The <code>runCommand<\/code> method calls the <code>collMod<\/code> database command, which lets you modify options on the specified collection. In this case, the command calls the <code>validator<\/code> method, just like you saw in the previous article when defining validation rules. This time, however, the method\u2019s argument is an empty document (curly brackets), which means that no rules will be defined. If rules already exist, they will be removed.<\/p>\n<p>When you run this statement, you should receive an OK message that indicates the statement successfully executed. Of course, you could have dropped and re-created the collection, rather than deleting the documents and schema rules. It\u2019s up to you which approach you take, although it can be useful to know how to remove validation rules.<\/p>\n<p>Once you have a clean slate, you should run the following <code>insertMany<\/code> statement, which adds four simple documents to the <code>candidates<\/code> collection:<\/p>\n<pre class=\"lang:none theme:none\">db.candidates.insertMany([\n  { _id: 101,\n    \"name\": \"Drew\", \n    \"dob\": \"1973-9-12\" },\n  { _id: 102,\n    \"name\": \"Parker\", \n    \"dob\": new Date(\"1982-12-2\") },\n  { _id: 103,\n    \"name\": \"Harper\", \n    \"dob\": \"1967-3-25\" },\n  { _id: 104,\n    \"name\": \"Darcy\", \n    \"dob\": new Date(\"1999-5-18\") }\n]);<\/pre>\n<p>The <code>dob<\/code> values in these documents are intentionally defined with different data types\u2014two as <code>String<\/code> values and two as <code>Date<\/code> values. The difference in types will help to demonstrate how to find valid and invalid documents, as you\u2019ll see shortly. When you run the <code>insertMany<\/code> statement, it should return the following results, which indicate that the documents have been added to the collection:<\/p>\n<pre class=\"lang:none theme:none\">{\n  acknowledged: true,\n  insertedIds: {\n    '0': 101,\n    '1': 102,\n    '2': 103,\n    '3': 104\n  }\n}<\/pre>\n<p>After you add the documents, you can run the following <code>runCommand<\/code> statement to define a simple set of schema validation rules:<\/p>\n<pre class=\"lang:none theme:none\">db.runCommand( { collMod: \"candidates\",\n  validator: {\n    $jsonSchema: {\n      bsonType: \"object\",\n      required: [ \"name\", \"dob\" ],\n      properties: {\n        \"name\": { bsonType: \"string\" },\n        \"dob\": { bsonType: \"date\" }\n      }\n    }\n  }\n});<\/pre>\n<p>The statement calls the <code>validator<\/code> method, which in turn calls the <code>$jsonSchema<\/code> operator. The operator defines a JSON Schema object that contains the validation rules. Notice that the <code>properties<\/code> element specifies that the <code>dob<\/code> field must be the <code>date<\/code> type. The rest of the statement\u2019s components work just like you saw in the previous article. If you have any questions about what I\u2019ve done here, refer to that article.<\/p>\n<p>Although the documents and validation rules that we\u2019ve added to the collection are relatively simple, they are enough to demonstrate how to find valid and invalid documents. The same principles apply no matter how complex your documents or validation rules.<\/p>\n<p>When working with a collection\u2019s schema validation, there might be times when you want to view or retrieve the validation rules themselves. For this, you can use the <code>getCollectionInfos<\/code> database method, specifying the <code>validator<\/code> option, as shown in the following statement:<\/p>\n<pre class=\"lang:none theme:none\">db.getCollectionInfos( \n  { name: \"candidates\" } )[0].options.validator;<\/pre>\n<p>The <code>getCollectionInfos<\/code> method lets you view different options about the specified collection, in this case, <code>candidates<\/code>. To retrieve the validation rules, you must specify the <code>validator<\/code> option as it is constructed here. The statement should return the following <code>$jsonSchema<\/code> object:<\/p>\n<pre class=\"lang:none theme:none\">{\n  '$jsonSchema': {\n    bsonType: 'object',\n    required: [ 'name', 'dob' ],\n    properties: { name: { bsonType: 'string' }, dob: { bsonType: 'date' } }\n  }\n}<\/pre>\n<p>Together, the <code>runCommand<\/code> method and <code>validator<\/code> option make it easy to retrieve a collection\u2019s validation rules so you can see how they\u2019ve been defined. You can also use this approach to find valid and nonvalid documents.<\/p>\n<p>To search for valid documents, you need to include the JSON Schema object as an argument to the <code>find<\/code> collection method. A good way to do this is to assign the object to a variable and then pass the variable in as an argument to the <code>find<\/code> method. For example, the following <code>let<\/code> statement assigns the JSON Schema object returned by the <code>getCollectionInfos<\/code> method to the <code>schema1<\/code> variable:<\/p>\n<pre class=\"lang:none theme:none\">let schema1 = \n  db.getCollectionInfos( \n    { name: \"candidates\" } )[0].options.validator;<\/pre>\n<p>After you define the variable, you can pass it into the <code>find<\/code> statements that you run within the same MongoDB Shell session. Before I demonstrate how to do this, however, I want to first show you how to assign the JSON Schema object definition directly to the variable, without using the <code>getCollectionInfos<\/code> method. In this way, you can check for valid and invalid documents before you define validation rules on a collection.<\/p>\n<p>To assign the JSON Schema object directly to the variable, use the <code>$jsonSchema<\/code> operator to define the object, using this as the variable value:<\/p>\n<pre class=\"lang:none theme:none\">let schema1 =\n{\n  $jsonSchema: {\n    bsonType: \"object\",\n    required: [ \"name\", \"dob\" ],\n    properties: {\n      \"name\": { bsonType: \"string\" },\n      \"dob\": { bsonType: \"date\" }\n    }\n  }\n};<\/pre>\n<p>Regardless of which approach you use to define your variable, you can easily verify its contents by running the following <code>print<\/code> command:<\/p>\n<pre class=\"lang:none theme:none\">print(schema1);<\/pre>\n<p>The command should return the <code>$jsonSchema<\/code> object, as shown in the following results:<\/p>\n<pre class=\"lang:none theme:none\">{\n  '$jsonSchema': {\n    bsonType: 'object',\n    required: [ 'name', 'dob' ],\n    properties: { name: [Object], dob: [Object] }\n  }\n}<\/pre>\n<p>After you define the <code>schema1<\/code> variable you can use it in your <code>find<\/code> statements to search for valid and invalid documents. For example, the following <code>find<\/code> statement searches the <code>candidates<\/code> collection for documents that conform to the JSON Schema object in the <code>schema1<\/code> variable:<\/p>\n<pre class=\"lang:none theme:none\">db.candidates.find( schema1 );<\/pre>\n<p>The statement returns the following results, which include the documents with the <code>_id<\/code> values of <code>102<\/code> and <code>104<\/code>:<\/p>\n<pre class=\"lang:none theme:none\">{\n  _id: 102,\n  name: 'Parker',\n  dob: 1982-12-02T08:00:00.000Z\n}\n{\n  _id: 104,\n  name: 'Darcy',\n  dob: 2003-07-02T07:00:00.000Z\n}<\/pre>\n<p>If you want to search for the documents that do not conform to the validation rules, you can use the <code>$nor<\/code> logical operator, along with the <code>schema1<\/code> variable:<\/p>\n<pre class=\"lang:none theme:none\">db.candidates.find( { $nor: [ schema1 ] } );<\/pre>\n<p>This time, the <code>find<\/code> statement returns only the invalid documents, which include the documents with the <code>_id<\/code> values of <code>101<\/code> and <code>103<\/code>:<\/p>\n<pre class=\"lang:none theme:none\">{\n  _id: 101,\n  name: 'Drew',\n  dob: '1973-9-12'\n}\n{\n  _id: 103,\n  name: 'Harper',\n  dob: '1967-3-25'\n}<\/pre>\n<p>As you can see, the value for the <code>dob<\/code> field in the results is a <code>String<\/code> value in both cases, which violates the validation rules. The field must take a <code>Date<\/code> value to conform to the rules. Except for this issue, the documents conform to the validation rules in all other ways.<\/p>\n<h2>Bypassing schema validation in a MongoDB collection<\/h2>\n<p>At times, you might want to add a document to a collection that violates the validation rules. For example, you might need to restore data from an archive file that includes invalid documents, which you want to preserve them in their original state.<\/p>\n<p>As you saw in the previous article, MongoDB will return an error when you try to insert a document that violates the validation rules. For instance, MongoDB returns an error if you try to run the following <code>insertOne<\/code> statement:<\/p>\n<pre class=\"lang:none theme:none\">db.candidates.insertOne(\n  {\n    _id: 105,\n    \"name\": \"Carey\", \n    \"dob\": \"2003-7-2\"\n  }\n);<\/pre>\n<p>The statement attempts to insert a document whose <code>dob<\/code> field is a <code>String<\/code> value, which violates the schema we defined above. However, you can override this behavior by including the <code>bypassDocumentValidation<\/code> option in your <code>insertOne<\/code> statement, as in the following example:<\/p>\n<pre class=\"lang:none theme:none\">db.candidates.insertOne(\n  {\n    _id: 105,\n    \"name\": \"Carey\", \n    \"dob\": \"2003-7-2\"\n  },\n  { bypassDocumentValidation: true }\n);<\/pre>\n<p>The <code>bypassDocumentValidation<\/code> option takes a Boolean as its value. When the option is set to <code>true<\/code>, MongoDB ignores the validation rules and inserts the document into the collection. The option works the same way for an <code>insertMany<\/code> statement.<\/p>\n<p>When you include the <code>bypassDocumentValidation<\/code> option in an <code>insertOne<\/code> or <code>insertMany<\/code> statement, the option applies only when you run the statement. Once you insert the document into the collection, you cannot update it in a way the violates the validation rules. For example, if you try to run the following <code>updateOne<\/code> statement, MongoDB will return an error message stating that the document failed validation:<\/p>\n<pre class=\"lang:none theme:none\">db.candidates.updateOne(\n  { _id : 105 },\n  { $set: { \"dob\" : \"2003-7-3\" } }\n);<\/pre>\n<p>However, the <code>updateOne<\/code> method, as well as the <code>updateMany<\/code> method, also support the <code>bypassDocumentValidation<\/code> option, as in the following example:<\/p>\n<pre class=\"lang:none theme:none\">db.candidates.updateOne(\n  { _id : 105 },\n  { $set: { \"dob\" : \"2003-7-3\" } },\n  { bypassDocumentValidation: true }\n);<\/pre>\n<p>When you run this statement, MongoDB ignores the validation rules, updates the document, and returns a message indicating that one document has been modified.<\/p>\n<p>As with inserting data, the <code>bypassDocumentValidation<\/code> option applies only to the <code>updateOne<\/code> or <code>updateMany<\/code> statements when you run them. If you later try to update the statement, it must once again conform to the validation rules or include the <code>bypassDocumentValidation<\/code> option.<\/p>\n<h2>Updating invalid documents in a MongoDB collection<\/h2>\n<p>By default, MongoDB applies validation rules whenever you try to insert or update a document, unless you include the <code>bypassDocumentValidation<\/code> option in your statements. However, MongoDB does not apply those rules to the documents that already exist in the collection at the time you define the validation rules, which means your collection could contain invalid documents.<\/p>\n<p>In some cases, you might want to update the invalid documents to bring them into conformance with the validation rules or to mark them in some way as being invalid. Before you update the documents, however, you can first search for them so you can assess what you have. For this, you can again use the <code>find<\/code> method, along with the <code>$nor<\/code> operator and JSON Schema object variable.<\/p>\n<p>You can use the <code>schema1<\/code> variable you defined earlier as long you\u2019re working in the same user session. If you\u2019ve reconnected to MongoDB since running those earlier statements, you\u2019ll need to redefine the variable before you can use it, in which case, you should again run the following <code>let<\/code> statement:<\/p>\n<pre class=\"lang:none theme:none\">let schema1 = \n  db.getCollectionInfos( \n    { name: \"candidates\" } )[0].options.validator;<\/pre>\n<p>Once you\u2019ve defined the variable, you can then run your <code>find<\/code> statement:<\/p>\n<pre class=\"lang:none theme:none\">db.candidates.find( { $nor: [ schema1 ] } );<\/pre>\n<p>The statement returns the following results, which indicate that the <code>candidates<\/code> collection contains three invalid documents:<\/p>\n<pre class=\"lang:none theme:none\">{\n  _id: 101,\n  name: 'Drew',\n  dob: '1973-9-12'\n}\n{\n  _id: 103,\n  name: 'Harper',\n  dob: '1967-3-25'\n}\n{\n  _id: 105,\n  name: 'Carey',\n  dob: '2003-7-3'\n}<\/pre>\n<p>To update the invalid documents, you can use <code>$nor<\/code> operator and <code>schema1<\/code> variable within an <code>updateMany<\/code> statement as part of the statement\u2019s filter. For example, the following <code>updateMany<\/code> statement uses the operator and variable to change the <code>dob<\/code> field in the invalid documents:<\/p>\n<pre class=\"lang:none theme:none\">db.candidates.updateMany(\n  { $nor: [ schema1 ] },\n  [ { $set: { \"dob\": { $toDate: \"$dob\" } } } ]\n);<\/pre>\n<p>The statement first searches for the invalid documents\u2014using the <code>$nor<\/code> operator and the <code>schema1<\/code> variable\u2014and then uses the <code>$toDate<\/code> method to set the field\u2019s data type to <code>Date<\/code>. When you run the statement, you should receive a message indicating that the three documents were modified. If you were to examine the documents, you would find that the <code>dob<\/code> field in each document is now defined with the <code>Date<\/code> data type.<\/p>\n<p>In this case, the <code>updateMany<\/code> statement modifies all invalid documents because it assumes that the <code>dob<\/code> value needs to be updated in every one of those documents. However, there might be times when you need to refine your statement\u2019s filter to target only a subset of the invalid documents, as in the following example:<\/p>\n<pre class=\"lang:none theme:none\">db.candidates.updateMany(\n  { $nor: [ schema1 ], \"dob\": { $type : \"string\" } },\n  [ { $set: { \"dob\": { $toDate: \"$dob\" } } } ]\n);<\/pre>\n<p>This time, the <code>updateMany<\/code> statement looks for documents that are invalid documents <em>and<\/em> whose <code>dob<\/code> field has a <code>String<\/code> value. If there are documents that violate the validation rules in other ways, they will not be updated.<\/p>\n<h2>Deleting invalid documents in a MongoDB collection<\/h2>\n<p>You can use the same logic\u2014the <code>$nor<\/code> operator and <code>schema1<\/code> variable\u2014when deleting invalid documents. For example, suppose you insert the following document into the <code>candidates<\/code> collection:<\/p>\n<pre class=\"lang:none theme:none\">db.candidates.insertOne(\n  {\n    _id: 106,\n    \"name\": \"Avery\", \n    \"dob\": \"1993-11-24\"\n  },\n  { bypassDocumentValidation: true }\n);<\/pre>\n<p>Notice that the document includes the <code>bypassDocumentValidation<\/code> option, allowing the document to be added even if it violates the validation rules, which it does.<\/p>\n<p>After you insert the document, you might decide to delete it, along with any other invalid documents in the collection. For this, you can use a <code>deleteMany<\/code> statement, once again incorporating the <code>$nor<\/code> operator and <code>schema1<\/code> variable, as in the following example:<\/p>\n<pre class=\"lang:none theme:none\">db.candidates.deleteMany( { $nor: [ schema1 ] } );<\/pre>\n<p>When you run the statement, MongoDB should return a message indicating that one document has been deleted (assuming you\u2019ve been following along with the examples). You can verify the deletion by running the following <code>find<\/code> statement:<\/p>\n<pre class=\"lang:none theme:none\">db.candidates.find( { $nor: [ schema1 ] } );<\/pre>\n<p>The statement should now return no results because the <code>candidates<\/code> collection no longer contains invalid documents. At this point, the collection should include only five documents, all of them in conformance with the validation rules. In other words, the <code>dob<\/code> field in each document is now defined with the <code>Date<\/code> data type.<\/p>\n<h2>Setting the schema validation action and level<\/h2>\n<p>The examples in this article, as well as those in the previous article, demonstrated how validation rules can affect your insert and update operations. As you have seen, you can insert documents only if they conform to those rules, unless you specify the <code>bypassDocumentValidation<\/code> option. Likewise, you can update documents only if the updated documents will conform to the rules.<\/p>\n<p>However, this is only the default behavior. You can actually control how inserts and updates are handled when defining your validation rules. To implement these controls, you must include one or both of the following options when defining your validation rules:<\/p>\n<ul>\n<li><code><strong>validationAction.<\/strong><\/code> Determines whether MongoDB generates an error or warning when a document violates the validation rules. If the option is set to <code>error<\/code> (the default), MongoDB rejects the inserted or updated document and issues an error. If the option is set to <code>warn<\/code>, MongoDB permits the document to be inserted or updated, but records the violation in the MongoDB log.<\/li>\n<li><code><strong>validationLevel.<\/strong><\/code> Determines how MongoDB should apply the validation rules. If the option is set to <code>strict<\/code> (the default), MongoDB applies the rules to all inserted and updated documents. If the option is set to <code>moderate<\/code>, MongoDB applies the rules to all inserted documents but only to updates in which the document being updated is already valid. If the document is invalid, MongoDB does not enforce the validation rules during the update.<\/li>\n<\/ul>\n<p>Let\u2019s take a look at a few examples to better understand how these options work. If you want to try them out for yourself, first run the following statements, which delete all the documents, removes the validation rules, and adds the original documents back into the collection:<\/p>\n<pre class=\"lang:none theme:none\">db.candidates.deleteMany({});\ndb.runCommand( { collMod: \"candidates\", validator: {} } );\ndb.candidates.insertMany([\n  { _id: 101,\n    \"name\": \"Drew\", \n    \"dob\": \"1973-9-12\" },\n  { _id: 102,\n    \"name\": \"Parker\", \n    \"dob\": new Date(\"1982-12-2\") },\n  { _id: 103,\n    \"name\": \"Harper\", \n    \"dob\": \"1967-3-25\" },\n  { _id: 104,\n    \"name\": \"Darcy\", \n    \"dob\": new Date(\"1999-5-18\") }\n]);<\/pre>\n<p>The next step is the define the validation rules, once again using a <code>runCommand<\/code> statement. This time, however, you should include the <code>validationAction<\/code> and <code>validationLevel<\/code> options in your <code>collMod<\/code> command, as in the following example:<\/p>\n<pre class=\"lang:none theme:none\">db.runCommand( { collMod: \"candidates\",\n  validator: {\n    $jsonSchema: {\n      bsonType: \"object\",\n      required: [ \"name\", \"dob\" ],\n      properties: {\n        \"name\": { bsonType: \"string\" },\n        \"dob\": { bsonType: \"date\" }\n      }\n    }\n  },\n  validationAction: \"warn\",\n  validationLevel: \"strict\"\n});<\/pre>\n<p>The <code>runCommand<\/code> statement defines the same validation rules we\u2019ve been using throughout this article, but it also includes the two validation options. The <code>validationLevel<\/code> option is set to its default value, <code>strict<\/code>, so nothing has changed there, but the <code>validationAction<\/code> option is set to <code>warn<\/code>, which changes MongoDB\u2019s default behavior.<\/p>\n<p>We can test this change by trying to insert a document into the <code>candidates<\/code> collection. The following <code>insertOne<\/code> statement attempts to add an invalid document to the collection, without including the <code>bypassDocumentValidation<\/code> option:<\/p>\n<pre class=\"lang:none theme:none\">db.candidates.insertOne(\n  {\n    _id: 105,\n    \"name\": \"Carey\", \n    \"dob\": \"2003-7-2\"\n  }\n);<\/pre>\n<p>If the <code>validationAction<\/code> option were set to <code>error<\/code> (the default), the <code>insertOne<\/code> statement would return an error. Instead, the option is set to <code>warn<\/code>, so MongoDB adds the document to the collection and records the violation in the MongoDB log. (To view the log on Atlas, refer to the Atlas documentation.)<\/p>\n<p>This principle works the same when updating documents. For example, the following <code>updateOne<\/code> statement attempts to update a field to an invalid value, without including the <code>bypassDocumentValidation<\/code> option:<\/p>\n<pre class=\"lang:none theme:none\">db.candidates.updateOne(\n  { _id : 105 },\n  { $set: { \"dob\" : \"2003-7-3\" } }\n);<\/pre>\n<p>As with the <code>insertOne<\/code> statement, MongoDB does not return an error but instead updates the document and records the violation in the MongoDB log.<\/p>\n<p>Now let\u2019s modify our validation option settings, this time setting the <code>validationAction<\/code> option to <code>error<\/code> (the default) and the <code>validationLevel<\/code> option to <code>moderate<\/code>:<\/p>\n<pre class=\"lang:none theme:none\">db.runCommand( { collMod: \"candidates\",\n  validator: {\n    $jsonSchema: {\n      bsonType: \"object\",\n      required: [ \"name\", \"dob\" ],\n      properties: {\n        \"name\": { bsonType: \"string\" },\n        \"dob\": { bsonType: \"date\" }\n      }\n    }\n  },\n  validationAction: \"error\",\n  validationLevel: \"moderate\"\n});<\/pre>\n<p>As you\u2019ll recall, the <code>candidates<\/code> collection includes two documents whose <code>dob<\/code> field is a <code>String<\/code> value and two documents whose <code>dob<\/code> field is a <code>Date<\/code> value. As a result, the documents with the <code>_id<\/code> values <code>101<\/code> and <code>103<\/code> are invalid.<\/p>\n<p>Let\u2019s try to update the <code>103<\/code> document by changing the <code>dob<\/code> value from <code>1967-3-25<\/code> to <code>1968-3-25<\/code>:<\/p>\n<pre class=\"lang:none theme:none\">db.candidates.updateOne(\n  { _id : 103 },\n  { $set: { \"dob\" : \"1968-3-25\" } }\n);<\/pre>\n<p>If the <code>validationLevel<\/code> option were set to <code>strict<\/code> (the default), the <code>updateOne<\/code> statement would return an error. Instead, MongoDB updates the document without generating an error or warning because the document was already invalid.<\/p>\n<p>You can test this out further by running the following <code>updateOne<\/code> statement, which attempts to update a valid document with an invalid <code>dob<\/code> value:<\/p>\n<pre class=\"lang:none theme:none\">db.candidates.updateOne(\n  { _id : 104 },\n  { $set: { \"dob\" : \"1999-6-18\" } }\n);<\/pre>\n<p>This time, MongoDB will return an error stating that the document failed validation. Because the document is already valid, MongoDB applies the validation rules to the document when you try to update it.<\/p>\n<p>In some cases, you might want to set your validation options to their default values. For example, you might have changed them temporarily to test a particular scenario and now want to change them back. To return them to their default state, you can run the following <code>runCommand<\/code> statement:<\/p>\n<pre class=\"lang:none theme:none\">db.runCommand( { collMod: \"candidates\",\n  validator: {\n    $jsonSchema: {\n      bsonType: \"object\",\n      required: [ \"name\", \"dob\" ],\n      properties: {\n        \"name\": { bsonType: \"string\" },\n        \"dob\": { bsonType: \"date\" }\n      }\n    }\n  },\n  validationAction: \"error\",\n  validationLevel: \"strict\"\n});<\/pre>\n<p>This statement will return the <code>candidates<\/code> collection to its default behavior, as it applies to the validation rules.<\/p>\n<h2>Getting started with MongoDB validation rules<\/h2>\n<p>In the previous article, I mentioned that schema validation can be a valuable tool for enforcing constraints on how a collection\u2019s documents are defined, but I also pointed out that you\u2019ll likely want to limit its use to more mature applications, when you don\u2019t require the same degree of flexibility you did when first setting up the collection. Enforcing schema validation on a schema prematurely can create more overhead. You should use schema validation judiciously until you fully understand how it will affect your applications.<\/p>\n<p>With that in mind, you should now have a good foundation for working with schema validation in the MongoDB collection, at least enough to get started. There is certainly more that you can do with schema validation than what I\u2019ve covered here, so I recommend that you review other resources, particularly the MongoDB documentation. I suggest that you start with the topic <a href=\"https:\/\/www.mongodb.com\/docs\/manual\/core\/schema-validation\/\">Schema Validation<\/a>, which introduces you to validation rules in MongoDB.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the previous article in this series, I introduced you to schema validation in MongoDB. I described how you can define validation rules on a collection and how those rules validate document inserts and updates. In this article, I continue the discussion by explaining how to apply validation rules to documents that already exist in&#8230;&hellip;<\/p>\n","protected":false},"author":221841,"featured_media":103515,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[53,159161],"tags":[5618,159226],"coauthors":[6779],"class_list":["post-103514","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-featured","category-mongodb","tag-mongodb","tag-mongodbseriesrobertsheldon"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/103514","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/221841"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=103514"}],"version-history":[{"count":2,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/103514\/revisions"}],"predecessor-version":[{"id":103517,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/103514\/revisions\/103517"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media\/103515"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=103514"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=103514"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=103514"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=103514"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}