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确实很不错!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,686评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,668评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,160评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,736评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,847评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,043评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,129评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,872评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,318评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,645评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,777评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,861评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,589评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,687评论 2 351

推荐阅读更多精彩内容