Mongojet
Asynchronous (asyncio) MongoDB client for Python
Install / Use
/learn @romis2012/MongojetREADME
Mongojet
Async (asyncio) MongoDB client for Python. It uses Rust MongoDB driver and tokio under the hood. Mongojet is 2-4x faster than Motor (and 1.5-3.5x faster than PyMongo AsyncMongoClient) in high concurrency scenarios (see benchmarks below).
Requirements
- Python >= 3.9
- pymongo>=4.6.2 (only
bsonpackage is required)
Installation
pip install mongojet
Usage
Mongojet has an API similar to PyMongo/Motor (but not exactly the same)
Creating a Client
Typically, you should create a single instance of Client per application/process. All client options should be passed via MongoDB connection string.
from mongojet import create_client, ReadPreference
client = await create_client('mongodb://localhost:27017/test_database?maxPoolSize=16')
Getting a Database
default database
db = client.get_default_database()
database with specific name
db = client.get_database('test_database')
database with specific name and options
db = client.get_database('test_database', read_preference=ReadPreference(mode='secondaryPreferred'))
Getting a Collection
collection = db['test_collection']
with options
collection = db.get_collection('test_collection', read_preference=ReadPreference(mode='secondary'))
Inserting documents
insert_one
document = {'key': 'value'}
result = await collection.insert_one(document)
print(result)
#> {'inserted_id': ObjectId('...')}
insert_many
documents = [{'i': i} for i in range(1000)]
result = await collection.insert_many(documents)
print(len(result['inserted_ids']))
#> 1000
Find documents
find_one (to get a single document)
document = await collection.find_one({'i': 1})
print(document)
#> {'_id': ObjectId('...'), 'i': 1}
find (to get cursor which is an async iterator)
cursor = await collection.find({'i': {'$gt': 5}}, sort={'i': -1}, limit=10)
you can iterate over the cursor using the async for loop
async for document in cursor:
print(document)
or collect cursor to list of documents using to_list method
documents = await cursor.to_list()
find_many (to get list of documents in single batch)
documents = await collection.find_many({'i': {'$gt': 5}}, sort={'i': -1}, limit=10)
Counting documents
n = await collection.count_documents({'i': {'$gte': 500}})
print(n)
#> 500
Aggregating documents
cursor = await collection.aggregate(pipeline=[
{'$match': {'i': {'$gte': 10}}},
{'$sort': {'i': 1}},
{'$limit': 10},
])
documents = await cursor.to_list()
print(documents)
Updating documents
replace_one
result = await collection.replace_one(filter={'i': 5}, replacement={'i': 5000})
print(result)
#> {'matched_count': 1, 'modified_count': 1, 'upserted_id': None}
update_one
result = await collection.update_one(filter={'i': 5}, update={'$set': {'i': 5000}}, upsert=True)
print(result)
#> {'matched_count': 0, 'modified_count': 0, 'upserted_id': ObjectId('...')}
update_many
result = await collection.update_many(filter={'i': {'$gte': 100}}, update={'$set': {'i': 0}})
print(result)
#> {'matched_count': 900, 'modified_count': 900, 'upserted_id': None}
Deleting documents
delete_one
result = await collection.delete_one(filter={'i': 5})
print(result)
#> {'deleted_count': 1}
delete_many
result = await collection.delete_many(filter={'i': {'$gt': 5}})
print(result)
#> {'deleted_count': 94}
Working with GridFS
bucket = db.gridfs_bucket(bucket_name="images")
with open('/path/to/my/awesome/image.png', mode='rb') as file:
data = file.read()
result = await bucket.put(data, filename='image.png', content_type='image/png')
file_id = result['file_id']
with open('/path/to/my/awesome/image_copy.png', mode='wb') as file:
data = await bucket.get_by_id(file_id)
file.write(data)
await bucket.delete(file_id)
Simple benchmark (lower is better):
find_one
<!--  -->
insert_one

iterate over cursor

