Mongodb的ODM操作:pymodm

前言:前期开发直接对数据库进行CRUD,越到后期发现越发现效果不佳,所以查了查有没有类似ORM操作的工具。
发现以下几种mongodb的ODM:

PyMODM

PyMODM是一个类似于ORM的框架,位于PyMongo之上。PyMODM由MongoDB,Inc。的工程师维护,并且很快就采用了新的MongoDB功能。PyMODM是一个“核心”ODM,这意味着它提供了简单,可扩展的功能,其他库可以利用它来定位Django等平台。同时,PyMODM功能强大,足以用于自己开发应用程序。除了用于讨论项目的Gitter通道外,还提供了有关readthedocs的完整文档。

Humongolus

Humongolus是Python和MongoDB的轻量级ORM框架。这个名字来自MongoDB和Homunculus的组合(一个微型但完全形成的人体的概念)。Humongolus允许您使用强大的验证来创建模型/模式。它试图尽可能地使用pythonic并尽可能地暴露pymongo游标对象。该代码可从GitHub下载 。GitHub也提供了教程和用法示例。

Ming

Ming(the Merciless)是一个库,允许您在Py​​thon应用程序中对MongoDB数据库强制执行模式。它是由SourceForge在迁移到MongoDB的过程中开发的。有关 更多详细信息,请参阅介绍性博客文章

MongoEngine

MongoEngine是另一个类似于ORM的层,位于PyMongo之上。它允许您使用受Django ORM启发的语法为文档和查询集合定义模式。该代码可在GitHub上获得 ; 有关更多信息,请参阅教程

MotorEngine

MotorEngine是MongoEngine到Motor的一个端口,用于与Tornado异步访问。它实现了相同的建模API以便于数据移植,这意味着可以在MotorEngine中读取MongoEngine中定义的模型。该源 可在GitHub上获得

uMongo

uMongo是一个Python MongoDB ODM。它的出现源于两个需求:缺乏异步ODM以及使用现有ODM进行文档(un)序列化的难度。适用于多个驱动程序:PyMongo,TxMongo,motor_asyncio和mongomock。该源可在GitHub上获得

经过对比最终选择了PyMODM,因为它有mongo对比官方的工程师维护,而且跟Django的ORM非常一致(之前一直用Django来着)。

官方文档如下:

https://pymodm.readthedocs.io/en/latest/getting-started.html

文档的介绍还可以,但是更多的还是要去摸索。
ODM层无非就是定义模型,然后进行增删查改。

定义模型:

from pymodm.connection import connect
connect("mongodb://localhost:27017/myDatabase", alias="ODM")

from pymodm import MongoModel, EmbeddedMongoModel, fields
import pymongo, pymongo.collation

class Role(MongoModel):
    role_name = fields.CharField()
    weight = fields.IntegerField(min_value=1, max_value=100)
    menu_items = fields.ListField(blank=True)

    class Meta:
        connection_alias = 'ODM'
        collection_name = 'role'

class User(MongoModel):
    name = fields.CharField()
    password = fields.CharField()
    contact = fields.CharField(blank=True, default='')
    gender = fields.IntegerField(min_value=0, max_value=1)
    role = fields.ReferenceField(Role, on_delete=ReferenceField.CASCADE)


    class Meta:
        connection_alias = 'ODM'
        collection_name = 'user'
        indexes = [
            pymongo.IndexModel([('name', pymongo.ASCENDING)], collation=pymongo.collation.Collation('zh'))
        ]

connection_alias = ‘ODM’ 是链接的别名,可以直接用别名连接。
indexes: 建立索引,提高查询速度

模型的定义和Django的几乎一模一样,它的类型包括:

[‘CharField’, ‘IntegerField’, ‘BigIntegerField’, ‘ObjectIdField’,
‘BinaryField’, ‘BooleanField’, ‘DateTimeField’, ‘Decimal128Field’,
‘EmailField’, ‘FileField’, ‘ImageField’, ‘FloatField’,
‘GenericIPAddressField’, ‘URLField’, ‘UUIDField’,
‘RegularExpressionField’, ‘JavaScriptField’, ‘TimestampField’,
‘DictField’, ‘OrderedDictField’, ‘ListField’, ‘PointField’,
‘LineStringField’, ‘PolygonField’, ‘MultiPointField’,
‘MultiLineStringField’, ‘MultiPolygonField’, ‘GeometryCollectionField’,
‘EmbeddedDocumentField’, ‘EmbeddedDocumentListField’, ‘ReferenceField’]

主要分享ReferenceField, ListField, EmbeddedDocumentListField

ReferenceField:

这个是引用,相当于“外键”,它的删除规则有5种:

  • on_delete: The action to take (if any) when the referenced object
    is deleted. The delete rule should be one of the following:
    * :attr:ReferenceField.DO_NOTHING (default).什么都不做(默认)
    * :attr:ReferenceField.NULLIFY更改引用已删除对象的字段None
    * :attr:ReferenceField.CASCADE级联删除:删除引用的对象时,递归删除引用它的所有对象
    * :attr:ReferenceField.DENY不允许删除仍然引用它们的对象
    * :attr:ReferenceField.PULL如果删除的对象只是存储在列表中的许多其他引用中的一个,请从此列表中删除引用
ListField:

这个储存的是列表,如果没有这个对象查出来是[]

EmbeddedDocumentListField:
class Student(EmbeddedMongoModel):
    name = fields.CharField()
    age= fields.IntegerField()

class Classe(MongoModel):
    name= fields.CharField()
   student_items = fields.EmbeddedDocumentListField(Student, blank=True)

EmbeddedDocumentListField这个储存的是对象,先生成Student对象,再添加到列表中,最后保存到student_items中。注:Student没有自己的“_id”,也不能直接查。

CRUD

官方文档上有,不说了。
单条查询用get比较好,他有两个报错:

        try:
            user = User.objects.get({'_id': user_id})
        except User.DoesNotExist:
            # Handle User not existing.
            pass
        except User.MultipleObjectsReturned:
            pass
        else:
            return user
2019.03.29补充:

构建好的模型在两个文件之间无法直接import引用,其中一个需要用字符串方式引用,这样的话就无法利用本身的五种删除规则,这里pymodm提供了register_delete_rule函数,可用于一对一及一对多的删除:

  # 删除用户,作者置空
User.register_delete_rule(Book, 'creator',pymodm.fields.ReferenceField.NULLIFY)  

# 删除用户,书籍直接删除
User.register_delete_rule(Book, 'creator',pymodm.fields.ReferenceField.CASCADE)  

# 删除用户,判断有对应的书籍时不准删除用户
User.register_delete_rule(Book, 'creator',pymodm.fields.ReferenceField.DENY)  

或者举例:

class User(MongoModel):
    name = fields.CharField()
    password = fields.CharField()
    book_items = fields.ListField(fields.ReferenceField(Book), blank=True)

当删除图书时,book_items中对应的一项将会是None,手动删除又很麻烦,于是可以注册删除规则如下:

# 删除书籍,用户的书籍册中对应书籍删除
Book.register_delete_rule(User, "book_items", pymodm.fields.ReferenceField.PULL)  

此时再删除书籍时,作者对应的book_items中直接删除对应项,nice!

再补充一点,联合查询小记:
 books = list(Book.objects.aggregate(
        {'$lookup': {'from': User.Meta.collection_name, 'localField': 'creator', 'foreignField': '_id',
                     'as': 'creator'}},
        {'$match': {'$or': [search_condition, search_condition_name]}},
        {'$sort': {'name':ASCENDING,'year': ASCENDING}}, collation={'locale': 'zh'}))

pymodm确实很不错!

    原文作者:清晨起床敲代码
    原文地址: https://www.jianshu.com/p/3127abe50239
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞