mongoengine中collection名称自动生成机制浅探

项目碰到要使用mongodb的场景,以前只听过这一强大的文档数据库,但一直没有真正使用过,参考一下项目中已有的使用代码,是通过import mongoengine这一模块实现python服务对db中collection的增删查改。

mongoengine的项目网站http://mongoengine.org 中介绍到:

MongoEngine is a Document-Object Mapper (think ORM,but for document databases) for working with MongoDB from Python.

大意是,MongoEngine是一个针对在Python中方便使用MongoDB的文档对象的映射器(类似ORM(Object Relational Mapping),但是是针对文档数据库)

参考已有的代码时发现,代码通过定义一个继承mongoengine.Document(定义于mongoengine/document.py文件中)的Python类和db中的collection建立了映射关系,通过对类的操作即可实现对db中对应collection的操作。

例如UserInfo的类定义如下:

class UserInfo(Document):
    """
        用户数据对象
    """
    meta = { 
        'db_alias': user',indexes: [
            user_iduser_type
        ]   
    }   
 
    user_type = IntField(default=USER_COOP)
    user_id = StringField(default='',max_length=64)
    nickname = StringField(detault=)
 
    ctime = DateTimeField(default=datetime.utcnow)
    mtime = DateTimeField(default=datetime.utcnow)   

其中meta用于定义类的一些元信息,如db_alias代表要访问的mongodb中具体的db名称,indexes则定义索引(用处?)。

然而其中并没有发现指定访问的collection名称的代码,估计是根据某种特殊规则从类的信息推断生成出来的,这引起了我的好奇,想要探究一番其生成原理。

通过远程登录上mongodb,使用"show collections"查看user db中的collection列表,发现了名叫user_info的collection,实际测试也确认UserInfo类查询的具体数据来源于其中

通过进一步参考官方文档,发现meta中可以通过指定"collection"的key-value对人工指明UserInfo类绑定的collection,然而上述代码中并没有用到这一机制。官方文档中说到mongodb默认通过将Document子类的名称转换为小写来作为db中对应collection的名称:

By default,the MongoDB collection used to store documents created using a Document subclass will be the name of the subclass converted to lowercase. A different collection may be specified by providing collection to the meta dictionary in the class definition.

然而这样的话UserInfo对应的名称应该是userinfo,而不是user_info才对。

使用开源软件的优势果断凸显出来了,拜读源码,研究个清楚。

查找源码发现mongoengine中的Document类中定义有类成员my_metaclass和__metaclass,其类型均为TopLevelDocumentMetaclass,collection名称根据UserInfo自动生成的逻辑就在这里面。

# The __metaclass__ attribute is removed by 2to3 when running with Python3

 my_metaclass is defined so that metaclass can be queried in Python 2 & 3

my_metaclass = TopLevelDocumentMetaclass
    __metaclass__ = TopLevelDocumentMetaclass

TopLevelDocumentMetaclass的定义在mongoengine/base/metaclasses.py中:

 TopLevelDocumentMetaclass(DocumentMetaclass):

    Metaclass for top-level documents (i.e. documents that have their own

    collection in the database.

    

    ...

针对collection名称自动生成的逻辑就在其__new__函数之中,其会在meta中没有collection字段时,根据以下代码片段生成默认collection名称:

         Set default collection name

        if collection' not in meta:

           meta['] = ''.join(_%s' % c if c.isupper() else c

                                         for c in name).strip(_').lower()

看到这里就一切了然了,将name中的所有大写字母转换为小写+'_'的形式(UserInfo->_user_info),而后strip两边的'_'(_user_info->user_info)

相关文章

文章浏览阅读552次。com.mongodb.MongoQueryException: Quer...
文章浏览阅读635次,点赞9次,收藏8次。MongoDB 是一种 NoSQ...
文章浏览阅读2.1k次。和。_mongodb 日期类型
文章浏览阅读1.7k次。Scalestack等客户期待使用MongoDB Atla...
文章浏览阅读970次。SpringBoot整合中间件mongodb、ES_sprin...
文章浏览阅读673次。MongoDB 简介_尚医通sql