官方例子
import asyncio
import motor.motor_asyncio
client = motor.motor_asyncio.AsyncIOMotorClient('mongodb://localhost:27017')
db = client['test_database']
collection = db['test_collection']
async def do_find_one():
document: dict = await db.test_collection.find_one({'i': {'$lt': 1}})
print(document.get('_id'))
loop = asyncio.get_event_loop()
loop.run_until_complete(do_find_one())
思考
- test_collection集合里有哪些字段,分别代表什么意思?
- 开始是如何设置字段和index的呢?
- 结果能不能用对象的方式操作?dict -> object
- 通过json的object_hook参数,或者pip install addict
- 可以转,但转换后的结果能不能对应上集合,是否有更优雅的方式?
- 如果有个类似ORM可以定义Model就好了!
看看这个
from mongoengine import Document, DynamicDocument, fields
class BaseModel(Document):
"""模型基类,公共方法"""
meta = {"abstract": True}
def to_dict(self):
"""模型对象转字典,并把id对象字符串化"""
data = self.to_mongo().to_dict()
if "_id" in data:
data["id"] = data.pop("_id").__str__()
return data
@classmethod
def load_motor(cls, document: dict):
"""加载单个motor数据文档,转成mongoengine对象"""
if "_id" in document:
document["id"] = document.pop("_id")
return cls(**document)
class TestCollection(DynamicDocument, BaseModel):
"""测试集合"""
meta = {
"collection": "test_collection",
"db_alias": "test_database",
"indexes": [
{"fields": ("name", "code"), 'unique': True}
],
"ordering": ["i"],
}
i = fields.IntField()
code = fields.IntField(verbose_name="编号")
name = fields.StringField(max_length=255, verbose_name="名称")
- 官方代码的do_find_one异步方法修改成这样:
async def do_find_one():
document: dict = await db.test_collection.find_one({'i': {'$lt': 1}})
document: TestCollection = TestCollection.load_motor(document)
print(document.id))
return document.to_dict()
- 不知道是不是有点麻烦呢?不过我觉得使用结果时减少了很多[""]取值,以及有Model的存在,至少让代码更可读一些,不然别人接手后,除了看MongoDB数据字段,否则无法知道需要查什么数据,或者这个字段到底是什么意思。