Showing posts with label schema. Show all posts
Showing posts with label schema. Show all posts

Tuesday, 8 June 2021

MongoDB: How to add schema to the existing collection

You can apply a JSON schema to an existing collection using the collMod command.

 

Let’s create an employee collection by inserting some data into it.

> db.employee.insert({"empId" : 1, "name" : "Krishna"})
WriteResult({ "nInserted" : 1 })
>
>
> db.employee.insert({"empId" : 2, "name" : "Ram", "age" : 33})
WriteResult({ "nInserted" : 1 })
>
>
> 
> db.employee.find().pretty()
{
  "_id" : ObjectId("60c038918d62325981fe3ca9"),
  "empId" : 1,
  "name" : "Krishna"
}
{
  "_id" : ObjectId("60c038ba8d62325981fe3cab"),
  "empId" : 2,
  "name" : "Ram",
  "age" : 33
}

 

Attach schema to the existing collection

db.runCommand( {
   collMod: "employee",
   validator : {
      $jsonSchema : {
         bsonType: 'object',
         required: ['empId', 'firstName', 'lastName'],

         properties: {
            empId : {
               bsonType : 'int',
               description: 'empId must be an integer and mandatory property'
            },
            firstName : {
               bsonType: 'string',
               description: 'firstName must be a string and mandatory property'
            },
            lastName : {
               bsonType: 'string',
               description: 'lastName must be a string and mandatory property'
            },
            hobbies : {
               bsonType : 'array',
               description: 'Hobbies of user',
               items: {
                  bsonType: 'int'
               }
            },
            projects : {
               bsonType : 'array',
               description: 'Hobbies of user',
               required: ['pjtName', 'pjtId'],
               items: {
                  bsonType: 'object',
                  properties : {
                     pjtName : {
                        bsonType: 'string',
                        description: 'pjtName must be a string and mandatory property'
                     },
                     pjtId : {
                        bsonType: 'int',
                        description: 'pjtId must be a string and mandatory property'
                     }
                  }
               }
            }
         }

      }
   },
   validationLevel: "moderate"
} )

 

Let’s try to insert some invalid information

Employee with only empId and firstName.

> db.employee.insert({"empId": 123, "firstName": "Sailu"})
WriteResult({
	"nInserted" : 0,
	"writeError" : {
		"code" : 121,
		"errmsg" : "Document failed validation"
	}
})
>
>
> db.employee.insert({"empId": NumberInt(123), "firstName": "Sailu"})
WriteResult({
	"nInserted" : 0,
	"writeError" : {
		"code" : 121,
		"errmsg" : "Document failed validation"
	}
})

Employee with empId, firstName and lastName properties

> db.employee.insert({"empId": NumberInt(123), "firstName": "Sailu", "lastName" : "PTR"})
WriteResult({ "nInserted" : 1 })


Let’s try to add project property with some invalid information

> db.employee.insert({"empId": NumberInt(234), "firstName": "Keerthi", "lastName" : "Shetty", "projects": [{"pjtName": "CPCS", "pjtId": 123}]})
WriteResult({
	"nInserted" : 0,
	"writeError" : {
		"code" : 121,
		"errmsg" : "Document failed validation"
	}
})

  In the above example the property "pjtId" should be of type NumberInt. Let’s correct and insert the data.

 

> db.employee.insert({"empId": NumberInt(234), "firstName": "Keerthi", "lastName" : "Shetty", "projects": [{"pjtName": "CPCS", "pjtId": NumberInt(123)}]})
WriteResult({ "nInserted" : 1 })

 

Let’s print all the documents of employee collection.

> db.employee.find().pretty()
{
	"_id" : ObjectId("60c038918d62325981fe3ca9"),
	"empId" : 1,
	"name" : "Krishna"
}
{
	"_id" : ObjectId("60c038ba8d62325981fe3cab"),
	"empId" : 2,
	"name" : "Ram",
	"age" : 33
}
{
	"_id" : ObjectId("60c03a328d62325981fe3cae"),
	"empId" : 123,
	"firstName" : "Sailu",
	"lastName" : "PTR"
}
{
	"_id" : ObjectId("60c03a7a8d62325981fe3cb1"),
	"empId" : 234,
	"firstName" : "Keerthi",
	"lastName" : "Shetty",
	"projects" : [
		{
			"pjtName" : "CPCS",
			"pjtId" : 123
		}
	]
}

 

Note

Schema validation will only apply to new write operations it will not run against existing documents in the collection.

 

 

Previous                                                    Next                                                    Home

MongoDB: How to find the schema of a document in the collection?

Below snippet print the schema of a document.

function printDocumentSchema(doc, indent) {
    for (var key in doc) {
        if(typeof doc[key] == "function"){   
        	continue;
        }  
           
        print(indent, key, typeof doc[key]) ;    
        
        if (typeof doc[key] == "object") {            
        	printSchema(doc[key], indent + "\t");
        }
    }
};

 

Let’s try with an example.

 

Step 1: Insert some data into the collection.

> db.employee.insert({"empId": NumberInt(1), "name": "Krishna", "hobbies" : ["trekking"], "address" : {"city": "Bangalore", "country": "India"}})
WriteResult({ "nInserted" : 1 })

 

Step 2: Get the reference of document.

> doc = db.employee.findOne()
{
	"_id" : ObjectId("60bf9cc88d62325981fe3ca8"),
	"empId" : 1,
	"name" : "Krishna",
	"hobbies" : [
		"trekking"
	],
	"address" : {
		"city" : "Bangalore",
		"country" : "India"
	}
}

Step 3: Define printDocumentSchema function.

function printDocumentSchema(doc, indent) {
    for (var key in doc) {
        if(typeof doc[key] == "function"){   
        	continue;
        }  
           
        print(indent, key, typeof doc[key]) ;    
        
        if (typeof doc[key] == "object") {            
        	printDocumentSchema(doc[key], indent + "\t");
        }
    }
};

> function printDocumentSchema(doc, indent) {
...     for (var key in doc) {
...         if(typeof doc[key] == "function"){   
...         continue;
...         }  
...            
...         print(indent, key, typeof doc[key]) ;    
...         
...         if (typeof doc[key] == "object") {            
...         printDocumentSchema(doc[key], indent + "\t");
...         }
...     }
... };


Step 4: Call ‘printDocumentSchema’ function with doc as argument.

> printDocumentSchema(doc, "  ")
   _id object
  	 str string
  	 isObjectId boolean
   empId number
   name string
   hobbies object
  	 0 string
   address object
  	 city string
  	 country string


 

 

Previous                                                    Next                                                    Home

MongoDB: Validate documents while inserting (or) updating

In this post, I am going to explain how to validate documents in MongoDB.

 

There are two ways to add validation logic to the collection.

a.   specify schema at the time of collection creation

b.   Add schema to the existing collection

 

Specify schema at the time of collection creation

Let’s create an employee collection and define the schema for it.


db.createCollection('employee', {
	
	validator : {
		$jsonSchema : {
			bsonType: 'object',
			required: ['empId', 'firstName', 'lastName'],

			properties: {
				empId : {
					bsonType : 'int',
					description: 'empId must be an integer and mandatory property'
				},
				firstName : {
					bsonType: 'string',
					description: 'firstName must be a string and mandatory property'
				},
				lastName : {
					bsonType: 'string',
					description: 'lastName must be a string and mandatory property'
				},
				hobbies : {
					bsonType : 'array',
					description: 'Hobbies of user',
					items: {
						bsonType: 'int'
					}
				},
				projects : {
					bsonType : 'array',
					description: 'Hobbies of user',
					required: ['pjtName', 'pjtId'],
					items: {
						bsonType: 'object',
						properties : {
							pjtName : {
								bsonType: 'string',
								description: 'pjtName must be a string and mandatory property'
							},
							pjtId : {
								bsonType: 'int',
								description: 'pjtId must be a string and mandatory property'
							}
						}
					}
				}
			}

		}
	}
});

 

Let’s try to insert some invalid information

Employee with only empId and firstName.

> db.employee.insert({"empId": 1, "firstName": "Krishna"})
WriteResult({
	"nInserted" : 0,
	"writeError" : {
		"code" : 121,
		"errmsg" : "Document failed validation"
	}
})
>
>
> db.employee.insert({"empId": NumberInt(1), "firstName": "Krishna"})
WriteResult({
	"nInserted" : 0,
	"writeError" : {
		"code" : 121,
		"errmsg" : "Document failed validation"
	}
})

 

Employee with empId, firstName and lastName properties

 

> db.employee.insert({"empId": NumberInt(1), "firstName": "Krishna", "lastName" : "Gurram"})
WriteResult({ "nInserted" : 1 })

  Let’s try to add project property and invalid information to project object

 

> db.employee.insert({"empId": NumberInt(2), "firstName": "Keerthi", "lastName" : "Shetty", "projects": [{"pjtName": "CPCS", "pjtId": 123}]})
WriteResult({
	"nInserted" : 0,
	"writeError" : {
		"code" : 121,
		"errmsg" : "Document failed validation"
	}
})

 

In the above example the property "pjtId" should be of type NumberInt. Let’s correct and insert the data.

> db.employee.insert({"empId": NumberInt(2), "firstName": "Keerthi", "lastName" : "Shetty", "projects": [{"pjtName": "CPCS", "pjtId": NumberInt(123)}]})
WriteResult({ "nInserted" : 1 })

 

Let’s print all the documents of employee collection.

> db.employee.find().pretty()
{
	"_id" : ObjectId("60bf985412681e44943c7974"),
	"empId" : 1,
	"firstName" : "Krishna",
	"lastName" : "Gurram"
}
{
	"_id" : ObjectId("60bf997a12681e44943c797a"),
	"empId" : 2,
	"firstName" : "Keerthi",
	"lastName" : "Shetty",
	"projects" : [
		{
			"pjtName" : "CPCS",
			"pjtId" : 123
		}
	]
}

 

Can I add any additional properties other than schema defined ones?

Yes

 

For example, below snipped add age property to the document.

> db.employee.insert({"empId": NumberInt(3), "firstName": "Gopi", "lastName" : "Battu", "age": 33})
WriteResult({ "nInserted" : 1 })

 

Let’s print all the documents in employee collection.

> db.employee.find().pretty()
{
	"_id" : ObjectId("60bf9a4c12681e44943c797d"),
	"empId" : 1,
	"firstName" : "Krishna",
	"lastName" : "Gurram"
}
{
	"_id" : ObjectId("60bf9a6312681e44943c797f"),
	"empId" : 2,
	"firstName" : "Keerthi",
	"lastName" : "Shetty",
	"projects" : [
		{
			"pjtName" : "CPCS",
			"pjtId" : 123
		}
	]
}
{
	"_id" : ObjectId("60bf9af812681e44943c7981"),
	"empId" : 3,
	"firstName" : "Gopi",
	"lastName" : "Battu",
	"age" : 33
}

 

 

 

 

 

 

 

 

 

 

 

 

Previous                                                    Next                                                    Home

Thursday, 8 April 2021

Generate json schema from a java class

Using 'generateSchema' method of JsonSchemaGenerator class, we can generate a json schema.

 

Example

public static String getJsonSchema(Class<?> type) throws JsonProcessingException {
	ObjectMapper jacksonObjectMapper = new ObjectMapper();
	JsonSchemaGenerator schemaGen = new JsonSchemaGenerator(jacksonObjectMapper);
	JsonSchema schema = schemaGen.generateSchema(type);
	String schemaString = jacksonObjectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(schema);
	return schemaString;
}

 

Find the below working application.

 

Define Address and Employee model classes.

 

Address.java

 

package com.sample.app.model;

public class Address {

	private String street;
	private String city;
	private String country;

	public String getStreet() {
		return street;
	}

	public void setStreet(String street) {
		this.street = street;
	}

	public String getCity() {
		return city;
	}

	public void setCity(String city) {
		this.city = city;
	}

	public String getCountry() {
		return country;
	}

	public void setCountry(String country) {
		this.country = country;
	}

}

 

Employee.java

package com.sample.app.model;

import java.util.List;

public class Employee {

	private int id;
	private String firstName;
	private String lastName;
	private Address address;
	private List<String> hobbies;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public Address getAddress() {
		return address;
	}

	public void setAddress(Address address) {
		this.address = address;
	}

	public List<String> getHobbies() {
		return hobbies;
	}

	public void setHobbies(List<String> hobbies) {
		this.hobbies = hobbies;
	}

}

 

Define JsonSchemaUtil class.

 

JsonSchemaUtil.java

package com.sample.app.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.module.jsonSchema.JsonSchema;
import com.fasterxml.jackson.module.jsonSchema.JsonSchemaGenerator;

public class JsonSchemaUtil {

	public static String getJsonSchema(Class<?> type) throws JsonProcessingException {
		ObjectMapper jacksonObjectMapper = new ObjectMapper();
		JsonSchemaGenerator schemaGen = new JsonSchemaGenerator(jacksonObjectMapper);
		JsonSchema schema = schemaGen.generateSchema(type);
		String schemaString = jacksonObjectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(schema);
		return schemaString;
	}
}

 

Define SchemaFromClass.

 

SchemaFromClass.java

package com.sample.app;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.sample.app.model.Employee;
import com.sample.app.util.JsonSchemaUtil;

public class SchemaFromClass {

	public static void main(String args[]) throws JsonProcessingException {

		String jsonSchema = JsonSchemaUtil.getJsonSchema(Employee.class);

		System.out.println(jsonSchema);
	}

}

 

Output

{
  "type" : "object",
  "id" : "urn:jsonschema:com:sample:app:model:Employee",
  "properties" : {
    "id" : {
      "type" : "integer"
    },
    "firstName" : {
      "type" : "string"
    },
    "lastName" : {
      "type" : "string"
    },
    "address" : {
      "type" : "object",
      "id" : "urn:jsonschema:com:sample:app:model:Address",
      "properties" : {
        "street" : {
          "type" : "string"
        },
        "city" : {
          "type" : "string"
        },
        "country" : {
          "type" : "string"
        }
      }
    },
    "hobbies" : {
      "type" : "array",
      "items" : {
        "type" : "string"
      }
    }
  }
}

 

 

 

 

 

 

 

 

 

Previous                                                    Next                                                    Home