Package: pymongoose
PymongooseThis is a pymongo helper package, that let you make more complicated actions with your collections.
It gives you the possibility to populate between packages without needs of creating an aggregation by yourself.
Gives you the basic actions such as find, update and delete, with more simplicity.Pymongoose came with a Schema class that let you work with more efficiency and organizationFirst StepspipinstallpymongoosepymongoCreate a model:models/role.pyimportdatetimefrompymongooseimportmethodsfrompymongoose.mongo_typesimportTypes,Schema,MongoException,MongoErrorfrombsonimportjson_utilfrombson.objectidimportObjectIdclassRole(Schema):schema_name="roles"# Name of the schema that mongo uses# Attributesid=Nonename=Noneaction=Nonedef__init__(self,**kwargs):self.schema={"name":{"type":Types.String,"required":True},"actions":[{"type":Types.String,"required":True}]}super().__init__(self.schema_name,self.schema,kwargs)def__str__(self):returnf"Role:{self.name}, Actions:{self.action}"Is higly recommended to follow this model for any schemaMongo ConfigurationThis mongo configuration is required for pymongoose to work correctlydb.py:importos,tracebackimportsignalfrompymongoimportMongoClientfrompymongoose.methodsimportset_schemas,get_cursor_lengthfrommodels.roleimportRoleMONGO_URI=os.environ.get("MONGO_URI")mongo_db=Nonedefmongo_init():globalmongo_dbclient=MongoClient(MONGO_URI)db=client.testtry:# Now schemas can be set in two ways#-> In a dict modeschemas={"roles":Role(empty=True).schema}set_schemas(db,schemas)#-> Or in a list modeset_schemas_from_list(db,[Role(empty=True)])print("MongoDB Connected!")except:traceback.print_exc()print("Error initializing database")exit(1)if__name__=="__main__":mongo_init()Examples:For more model examples check examples/Insert function:user=User(name="TestA",password="test",role=role.id)id=user.save()user.save() will throw an exception if a field marked as required in schema isNone.Find function:users=User.find({})foruserinusers:user=User.parse(user)This will return a cursor of elements, which can be parsed into User model for a better management.Find one function:user=User.find({},one=True)# ORuser=User.find_one({})This will return a User element with fields obtained by database, if you prefer a json just addparse=FalseAt last of thefindstatement.Find by id function:# this Function will search for "_id" field# so id must be a hex24 string or ObjectIduser=User.find_by_id(id)# for a complete useruser=User.find_by_id(id,select={"name":1,"username":1})# For a custom userThis will return a User element with fields obtained by database, if you prefer a json just addparse=FalseAt last of thefindstatement.Populate a search:user=User.find_by_id(id,populate=[{"path":"role","select":["name","actions"],"options":["actions"]}])# For an extensive populate# oruser=User.find_by_id(id,populate=["role"])# For a simple populateThis will return a User element with fields obtained by databasePopulate is a really useful tool when we work with difficult or complex models, with pymongoose you wont need to create an extensive aggregation to lookup for elements.Populate works with simple ids like:schema={"name":{"type":Types.String,"required":True},"role":{# <- Simple field"type":Types.ObjectId,"ref":"roles"}}lists:schema={"name":{"type":Types.String,"required":True},"logs":[{# <- List field"type":Types.ObjectId,"ref":"logs"}]}and complex modelsschema={"name":{"type":Types.String,"required":True},"friends":[{"friend":{"type":Types.ObjectId,# <- Complex list field"ref":"friends"},"frequent":{"type":Types.Boolean,"default":False}}]}Pymongoose can recursively populate fields like this:#menu schema:menu_schema={# ..."items":[{"type":Types.ObjectId,"ref":"items"}],# ...}#item schema:item_schema:{# ..."drink":{"type":Types.ObjectId,"ref":"drinks"},"dish":{"type":Types.ObjectId,"ref":"dishes"}# ...}#Populatemenus=Menu.find({},populate=[{"path":"items","options":["dish","drink"]}])formenuinmenus:print(menu)This will return a CursorCommand elementIn this example all menus populate each item of their array, at same time element dish and drink are populated, returning a complete array of populated menus with populated items.Parsed finds:pymongoosehas the ability to parse the return cursor as different types:
Available types are
- IFAS_DEFAULT(0), will return cursor if one == False, else a dict if parse == False
- IFAS_DICT(1), will return a list of dicts if one == False, else as serializable dict
- IFAS_STRING(2), will return a parsed list of dicts as str if one == False, else as a str parsed serializable dict*Note: In case you don't need a serializable dict, left cursorAS_DEFAULTUpdate item:count=User.update({},{"$set":{"password":"0"}},many=True)#many is set to False by defaultDelete item:count=User.delete({},many=True)#many is set to False by defaultNote:If you are working with vscode I have already created a model snippet to save you a lots of time:https://github.com/Djcharles26/pymongoose/blob/master/pymongoose-snippets.jsonFor using this you must copy them to your python snippets:CTRL + SHIFT + PConfigure User snippetspython.jsonCopy snippets in blobPaste them in your user python.json