Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Pymongo have validation rules built in?

I am trying to validate an inserted document against a schema, and was trying to find a way to validate the inserted document.

There are libraries like MongoEngine that say they do the work, but is there a way to do document validation directly via pymongo ?

like image 756
omrakhur Avatar asked Oct 04 '17 15:10

omrakhur


People also ask

How does MongoDB validate data?

To add document validation to an existing collection, use collMod command with the validator option. MongoDB also provides the following related options: validationLevel option, which determines how strictly MongoDB applies validation rules to existing documents during an update.

Does MongoDB support schema validation?

In the past developers implemented schema validation in their applications, but starting from version 3.6, MongoDB supports the JSON Schema Validator. We can rely on it to define a fixed schema and validation rules directly into the database and free the applications to take care of it.

Is PyMongo the same as MongoDB?

What is PyMongo? PyMongo is MongoDB's official native driver for Python. It's a library that lets you connect to a MongoDB database and query the data stored using the MongoDB Query API. It is the recommended way to interface with the document database.


1 Answers

The python driver docs are indeed a little light on how to use the db.command. Here is a complete working example:

    from pymongo import MongoClient
    from collections import OrderedDict
    import sys
    
    client = MongoClient()   # supply connection args as appropriate 
    db = client.testX
    
    db.myColl.drop()
    
    db.create_collection("myColl")  # Force create!
    
    #  $jsonSchema expression type is prefered.  New since v3.6 (2017):
    vexpr = {"$jsonSchema":
      {
             "bsonType": "object",
             "required": [ "name", "year", "major", "gpa" ],
             "properties": {
                "name": {
                   "bsonType": "string",
                   "description": "must be a string and is required"
                },
                "gender": {
                   "bsonType": "string",
                   "description": "must be a string and is not required"
                },
                "year": {
                   "bsonType": "int",
                   "minimum": 2017,
                   "maximum": 3017,
                   "exclusiveMaximum": False,
                   "description": "must be an integer in [ 2017, 3017 ] and is required"
                },
                "major": {
                   "enum": [ "Math", "English", "Computer Science", "History", None ],
                   "description": "can only be one of the enum values and is required"
                },
                "gpa": {
                   # In case you might want to allow doubles OR int, then add
                   # "int" to the bsonType array below:
                   "bsonType": [ "double" ],
                   "minimum": 0,
                   "description": "must be a double and is required"
                }
             }
      }
    }
    
    # Per the docs, args to command() require that the first kev/value pair
    # be the command string and its principal argument, followed by other
    # arguments.  There are two ways to do this:  Using an OrderDict:
    cmd = OrderedDict([('collMod', 'myColl'),
            ('validator', vexpr),
            ('validationLevel', 'moderate')]
    db.command(cmd)
    
    # Or, use the kwargs construct:
    # db.command('collMod','myColl', validator=vexpr, validationLevel='moderate')

    try:
        db.myColl.insert({"x":1})
        print "NOT good; the insert above should have failed."
    except:
        print "OK. Expected exception:", sys.exc_info()    
    
    try:
        okdoc = {"name":"buzz", "year":2019, "major":"Math", "gpa":3.8}
        db.myColl.insert(okdoc)
        print "All good."
    except:
        print "exc:", sys.exc_info()    
like image 115
Buzz Moschetti Avatar answered Sep 24 '22 17:09

Buzz Moschetti