python异步操作MongoDB之motor


  Motor 提供了一个基于协程的 API,用于从Tornadoasyncio MongoDB 的非阻塞访问。Motor 在连接到 MongoDB 或执行 I/O 时从不阻塞事件循环。Motor 封装了几乎所有 PyMongo 的 API 并使其成为非阻塞的。

 

  Motor PyMongo 一样,表示具有 4 级对象层次结构的数据:

  1.   AsyncIOMotorClient 代表一个mongod进程,或者它们的一个集群。您显式创建这些客户端对象之一,将其连接到正在运行的 mongod,并在应用程序的整个生命周期中使用它。
  2.   AsyncIOMotorDatabase:每个 mongod 都有一组数据库(磁盘上不同的数据文件集)。您可以从客户端获取对数据库的引用。
  3.   AsyncIOMotorCollection:一个数据库有一组集合,其中包含文档;您从数据库中获得对集合的引用。
  4.   AsyncIOMotorCursor:find()AsyncIOMotorCollection得到一个AsyncIOMotorCursor,它表示匹配查询的文档集。

 

一、安装:

python3 -m pip install motor

 motor2.2 版本要求:

  • python >= 3.5
  • Pymongo >= 3.12

 

二、使用:

1创建客户端

AsyncIOMotorClient您通常会在应用程序启动时创建单个实例

import motor.motor_asyncio

client = motor.motor_asyncio.AsyncIOMotorClient()

这将连接到mongod默认主机和端口上的侦听。您可以指定主机和端口,例如:

client = motor.motor_asyncio.AsyncIOMotorClient('localhost', 27017)

Motor 还支持连接 URI:

client = motor.motor_asyncio.AsyncIOMotorClient('mongodb://localhost:27017')

连接到集合,例如:

client = motor.motor_asyncio.AsyncIOMotorClient('mongodb://host1,host2/?replicaSet=my-replicaset-name')

  

2、获取数据库

一个 MongoDB 实例可以支持多个独立的数据库。从一个开放的客户端,您可以使用点表示法或括号表示法获得对特定数据库的引用:

db = client.test_database
或
db = client['test_database']

创建对数据库的引用没有 I/O,也不需要 await表达式。

 

3、获取集合

集合是存储在 MongoDB 中的一组 文档,可以认为大致相当于关系数据库中的表。在 Motor 中获取集合与获取数据库相同:

collection = db.test_collection
或
collection = db['test_collection']

就像获取对数据库的引用一样,获取对集合的引用不需要 I/O,也不需要await表达式。

 

4、插入文档

4.1 插入单条数据insert_one(),要在 MongoDB 中存储文档,请调用insert_one()表达式 await

async def do_insert():
    document = {'key': 'value'}
    result = await db.test_collection.insert_one(document)
    print('result %s' % repr(result.inserted_id))
import asyncio loop = asyncio.get_event_loop() loop.run_until_complete(do_insert()) result ObjectId('...')

 

4.2 大批量插入文档insert_many()

async def do_insert():
    result = await db.test_collection.insert_many(
        [{'i': i} for i in range(2000)])
    print('inserted %d docs' % (len(result.inserted_ids),))

loop = asyncio.get_event_loop()
loop.run_until_complete(do_insert())

 

4.3 使用find_one获取单个文档,用于find_one()获取与查询匹配的第一个文档。例如,要获取键“i”的值小于 1 的文档:

async def do_find_one():
    document = await db.test_collection.find_one({'i': {'$lt': 1}})
    pprint.pprint(document)

loop = asyncio.get_event_loop()
loop.run_until_complete(do_find_one())

 

4.4 查询多个文档用于find()查询一组文档。 find()没有 I/O,也不需要await 表达式。它只是创建一个AsyncIOMotorCursor实例。当您调用to_list() 或执行循环时,查询实际上是在服务器上执行的。

查找i”小于 5 的所有文档:

async def do_find():
    cursor = db.test_collection.find({'i': {'$lt': 5}}).sort('i')
    for document in await cursor.to_list(length=100):
        pprint.pprint(document)

loop = asyncio.get_event_loop()
loop.run_until_complete(do_find())

当您调用to_list以防止 Motor 缓冲无限数量的文档时,需要一个参数 length

您可以在循环中一次处理一个文档:async for

async def do_find():
    c = db.test_collection
    async for document in c.find({'i': {'$lt': 2}}):
        pprint.pprint(document)

loop = asyncio.get_event_loop()
loop.run_until_complete(do_find())

在开始迭代之前,您可以对查询进行sort、limit或skip:

async def do_find():
    cursor = db.test_collection.find({'i': {'$lt': 4}})
    # Modify the query before iterating
    cursor.sort('i', -1).skip(1).limit(2)
    async for document in cursor:
        pprint.pprint(document)

loop = asyncio.get_event_loop()
loop.run_until_complete(do_find())

游标实际上并不单独从服务器检索每个文档;它可以有效地大批量获取文档。

 

4.5 获取文档数,用于count_documents()确定集合中的文档数,或与查询匹配的文档数:

async def do_count():
    n = await db.test_collection.count_documents({})
    print('%s documents in collection' % n)
    n = await db.test_collection.count_documents({'i': {'$gt': 1000}})
    print('%s documents where i > 1000' % n)

loop = asyncio.get_event_loop()
loop.run_until_complete(do_count())

 

4.6 更新文档

4.6.1 单个文档全部更新:replace_one(),它需要两个参数:一个指定要替换哪个文档的查询和一个替换文档。该查询遵循与find_one()相同的语法。替换文档:

async def do_replace():
    coll = db.test_collection
    old_document = await coll.find_one({'i': 50})
    print('found document: %s' % pprint.pformat(old_document))
    _id = old_document['_id']
    result = await coll.replace_one({'_id': _id}, {'key': 'value'})
    print('replaced %s document' % result.modified_count)
    new_document = await coll.find_one({'_id': _id})
    print('document is now %s' % pprint.pformat(new_document))

loop = asyncio.get_event_loop()
loop.run_until_complete(do_replace())

您可以看到replace_one()它用新文档替换了旧文档中的所有的内容。

 

4.6.2 单个文档部分更新:update_one(),与 MongoDB 的修饰符运算符一起使用update_one()来更新文档的一部分并保持其余部分不变。

我们将找到“i”为 51 的文档,并使用$set 运算符将“key”设置为“value”:

async def do_update():
    coll = db.test_collection
    result = await coll.update_one({'i': 51}, {'$set': {'key': 'value'}})
    print('updated %s document' % result.modified_count)
    new_document = await coll.find_one({'i': 51})
    print('document is now %s' % pprint.pformat(new_document))

loop = asyncio.get_event_loop()
loop.run_until_complete(do_update())

key”设置为“value”,“i”仍然是 51

 

4.6.3 更新全部文档:update_many(),您可以使用以下命令更新所有文档

await coll.update_many({'i': {'$gt': 100}},
                       {'$set': {'key': 'value'}})

也可以看看 MongoDB 文档 更新

 

4.7  删除文档:  delete_many(),删除所有匹配的文档。

async def do_delete_many():
    coll = db.test_collection
    n = await coll.count_documents({})
    print('%s documents before calling delete_many()' % n)
    result = await db.test_collection.delete_many({'i': {'$gte': 1000}})
    print('%s documents after' % (await coll.count_documents({})))

loop = asyncio.get_event_loop()
loop.run_until_complete(do_delete_many())

 

项目地址:https://github.com/mongodb/motor

文档地址:https://motor.readthedocs.io/


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM