Python异步操作MongoDB --Motor的使用
<p></p><div class="toc"><div class="toc-container-header">目录</div><ul><li>安装</li><li>创建客户端<ul><li><ul><li>指定主机和端口号</li><li>使用用户名和密码</li></ul></li></ul></li><li>获取数据库</li><li>获取集合</li><li>插入文档(insert_one)</li><li>批量插入文档(insert_many)</li><li>查询一个文档(find_one)</li><li>查询多个文档(find)</li><li>使用 async for 查询所有文档</li><li>使用count_documents()查询集合中的文档数量</li><li>更新文档(推荐使用update_one或update_many)</li><li>删除文档<ul><li>转载自 https://juejin.im/post/6844903896813404173</li></ul></li></ul></div><p></p><h3 id="安装">安装</h3>
<pre><code>python3 -m pip install motor
</code></pre>
<h3 id="创建客户端">创建客户端</h3>
<h5 id="指定主机和端口号">指定主机和端口号</h5>
<pre><code>import motor.motor_asyncio
client = motor.motor_asyncio.AsyncIOMotorClient('localhost', 27017)
</code></pre>
<h5 id="使用用户名和密码">使用用户名和密码</h5>
<pre><code>motor.motor_asyncio.AsyncIOMotorClient('mongodb://root:123456@localhost:27017')
</code></pre>
<h3 id="获取数据库">获取数据库</h3>
<p>MongoDB的单个实例可以支持多个独立的数据库。在开放式客户端中,您可以使用点表示法或括号表示法来获取对特定数据库的引用:</p>
<pre><code>db = client.test_database
db = client['test_database']
</code></pre>
<p>创建对数据库的引用不会执行I / O,也不需要 <strong>await</strong> 表达式。</p>
<h3 id="获取集合">获取集合</h3>
<p>一个集合是一组存储在MongoDB中的文档,并且可以被认为是大致在关系数据库中的表的当量。获取Motor中的集合与获取数据库的工作方式相同:</p>
<pre><code>collection = db.test_collection
collection = db['test_collection']
</code></pre>
<p>就像获取对数据库的引用一样,获取对集合的引用不会产生I / O并且不需要 <strong>await</strong> 表达式。</p>
<h3 id="插入文档insert_one">插入文档(insert_one)</h3>
<p>与pymongo一样,Motor使用Python字典表示MongoDB文档。要存储在MongoDB中的文档,在 <strong>await</strong> 表达式中调用 <strong>insert_one()</strong> :</p>
<pre><code>async def do_insert():
document = {'key': 'value'}
result = await db.test_collection.insert_one(document)# insert_one只能插入一条数据
print('result %s' % repr(result.inserted_id))
loop = asyncio.get_event_loop()
loop.run_until_complete(do_insert())
# result ObjectId('...')
</code></pre>
<h3 id="批量插入文档insert_many">批量插入文档(insert_many)</h3>
<pre><code>async def do_insert():
result = await db.test_collection.insert_many(
[{'i': i} for i in range(2000)])# insert_many可以插入一条或多条数据,但是必须以列表(list)的形式组织数据
print('inserted %d docs' % (len(result.inserted_ids),))
loop = asyncio.get_event_loop()
loop.run_until_complete(do_insert())
# inserted 2000 docs
</code></pre>
<h3 id="查询一个文档find_one">查询一个文档(find_one)</h3>
<p>使用 <strong>find_one()</strong> 得到匹配查询的第一个文档。例如,要获取密钥“i”的值小于1的文档:</p>
<pre><code>async def do_find_one():
document = await db.test_collection.find_one({'i': {'$lt': 1}})# find_one只能查询一条数据
pprint.pprint(document)
loop = asyncio.get_event_loop()
loop.run_until_complete(do_find_one())
# {'_id': ObjectId('...'), 'i': 0}
</code></pre>
<p><strong>注意:结果是一个字典匹配我们之前插入的字典。</strong></p>
<h3 id="查询多个文档find">查询多个文档(find)</h3>
<p>使用 <strong>find()</strong> 要查询的一组文档。 <strong>find()</strong> 没有I / O,也不需要 <strong>await</strong>表达式。它只是创建一个 <strong>AsyncIOMotorCursor</strong> 实例。当您调用 <strong>to_list()</strong> 或为循环执行异步时 <strong>(async for)</strong> ,查询实际上是在服务器上执行的。</p>
<p>查询 “ i ” 小于5的所有文档:</p>
<pre><code>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())
# {'_id': ObjectId('...'), 'i': 0}
# {'_id': ObjectId('...'), 'i': 1}
# {'_id': ObjectId('...'), 'i': 2}
# {'_id': ObjectId('...'), 'i': 3}
# {'_id': ObjectId('...'), 'i': 4}
</code></pre>
<p><strong>一length</strong> ,调用方法 <strong>to_list</strong> 的必传参数,防止 <strong>Motor</strong> 从缓冲中获取的文档数量不受限制,此处限制为100。</p>
<h3 id="使用-async-for-查询所有文档">使用 async for 查询所有文档</h3>
<p>您可以在循环中一次处理一个文档:<strong>async for</strong></p>
<pre><code>async def do_find():
c = db.test_collection
async for document in c.find({}):# 查询所有文档
pprint.pprint(document)
loop = asyncio.get_event_loop()
loop.run_until_complete(do_find())
# {'_id': ObjectId('...'), 'i': 0}
# {'_id': ObjectId('...'), 'i': 1}
</code></pre>
<p>您可以在开始迭代之前对查询应用排序,跳过或限制:</p>
<pre><code>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)# 对查询应用排序(sort),跳过(skip)或限制(limit)
async for document in cursor:
pprint.pprint(document)
loop = asyncio.get_event_loop()
loop.run_until_complete(do_find())
# {'_id': ObjectId('...'), 'i': 2}
# {'_id': ObjectId('...'), 'i': 1}
</code></pre>
<p>游标 <strong>(cursor)</strong> 实际上并不是单独从服务器检索每个文档; 它可以大批量地获取文档。</p>
<h3 id="使用count_documents查询集合中的文档数量">使用count_documents()查询集合中的文档数量</h3>
<pre><code>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())
# 2000 documents in collection
# 999 documents where i > 1000
</code></pre>
<h3 id="更新文档推荐使用update_one或update_many">更新文档(推荐使用update_one或update_many)</h3>
<p><strong>replace_one()</strong> 更改文档。它需要两个参数:一个指定要替换哪个文档的<em>查询</em>和一个替换文档。该查询遵循与 <strong>find()</strong> 或 相同的语法 <strong>find_one()</strong> 。替换一个文档的示例:</p>
<pre><code>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']
old_document['i'] = -1# 修改文档(dict)的key, value
old_document['new'] = 'new'# 增加文档(dict)的key, value
del old_document['i']# 删除文档(dict)的key, value
result = await coll.replace_one(
{'_id': _id}, old_document)# replace_one第一个参数为查询条件, 第二个参数为更新后的文档
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())
# found document: {'_id': ObjectId('...'), 'i': 50}
# replaced 1 document
# document is now {'_id': ObjectId('...'), 'key': 'value'}
</code></pre>
<p>除了 <strong>_id</strong> 不变,<strong>replace_one()</strong> 会对修改后文档的所有字段做更新操作, <strong>慎用</strong> 。</p>
<p><strong>update_one()</strong> 与MongoDB的修饰符运算符一起使用来更新文档的一部分并保持其余部分不变。我们将找到“i”为51的文档,并使用 <strong>$set</strong> 运算符将“key”设置为“value”:</p>
<pre><code>async def do_update():
coll = db.test_collection
result = await coll.update_one({'i': 51}, {'$set': {'key': 'value'}})# 仅新增或更改该文档的某个key
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())
# updated 1 document
# document is now {'_id': ObjectId('...'), 'i': 51, 'key': 'value'}
</code></pre>
<p>“key”设置为“value”,“i”仍为51。</p>
<p><strong>update_one()</strong> 只影响它找到的第一个文档,您可以使用 <strong>update_many()</strong> 更新所有文档:</p>
<pre><code>await coll.update_many({'i': {'$gt': 100}}, {'$set': {'key': 'value'}})
</code></pre>
<h3 id="删除文档">删除文档</h3>
<p><strong>delete_many()</strong> 采用与语法相同的 <strong>find()</strong> 查询。<strong>delete_many()</strong> 立即删除所有匹配的文档。</p>
<pre><code>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())
# 2000 documents before calling delete_many()
# 1000 documents after
</code></pre>
<h4 id="转载自-httpsjuejinimpost6844903896813404173">转载自 https://juejin.im/post/6844903896813404173</h4><br><br>
来源:https://www.cnblogs.com/aduner/p/13532504.html
頁:
[1]