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