@@ -127,10 +127,10 @@ Some simple examples of what MongoEngine code looks like:
127127 >>> BlogPost.objects(tags='mongodb').count()
128128 1
129129
130- Async Support (Experimental)
131- ============================
132- MongoEngine now supports asynchronous operations using PyMongo's AsyncMongoClient.
133- This allows you to use async/await syntax for database operations :
130+ Async Support
131+ =============
132+ MongoEngine provides comprehensive asynchronous support using PyMongo's AsyncMongoClient.
133+ All major database operations are available with async/await syntax:
134134
135135.. code :: python
136136
@@ -142,22 +142,93 @@ This allows you to use async/await syntax for database operations:
142142 # Connect asynchronously
143143 await connect_async('mydb')
144144
145- # All document operations have async equivalents
145+ # Document operations
146146 post = TextPost(title='Async Post', content='Async content')
147147 await post.async_save()
148-
149- # Async queries
150- post = await TextPost.objects.async_get(title='Async Post')
148+ await post.async_reload()
151149 await post.async_delete()
152150
153- # Async reload
154- await post.async_reload()
151+ # QuerySet operations
152+ post = await TextPost.objects.async_get(title='Async Post')
153+ posts = await TextPost.objects.filter(tags='python').async_to_list()
154+ count = await TextPost.objects.async_count()
155+
156+ # Async iteration
157+ async for post in TextPost.objects.filter(published=True):
158+ print(post.title)
159+
160+ # Bulk operations
161+ await TextPost.objects.filter(draft=True).async_update(published=True)
162+ await TextPost.objects.filter(old=True).async_delete()
163+
164+ # Reference field async fetching
165+ # In async context, references return AsyncReferenceProxy
166+ if hasattr(post, 'author'):
167+ author = await post.author.async_fetch()
168+
169+ # Transactions
170+ from mongoengine import async_run_in_transaction
171+ async with async_run_in_transaction():
172+ await post1.async_save()
173+ await post2.async_save()
174+
175+ # GridFS async operations
176+ from mongoengine import FileField
177+ class MyDoc(Document):
178+ file = FileField()
179+
180+ doc = MyDoc()
181+ await MyDoc.file.async_put(file_data, instance=doc)
182+
183+ # Context managers
184+ from mongoengine import async_switch_db
185+ async with async_switch_db(MyDoc, 'other_db'):
186+ await doc.async_save()
155187
156- # Run the async function
157188 asyncio.run(main())
158189
159- Note: Async support is experimental and currently includes basic CRUD operations.
160- QuerySet async methods and advanced features are still under development.
190+ **Supported Async Features: **
191+
192+ - **Document Operations **: async_save(), async_delete(), async_reload()
193+ - **QuerySet Operations **: async_get(), async_first(), async_count(), async_create()
194+ - **Bulk Operations **: async_update(), async_delete(), async_update_one()
195+ - **Async Iteration **: Support for ``async for `` with QuerySets
196+ - **Reference Fields **: async_fetch() for explicit dereferencing
197+ - **GridFS **: async_put(), async_get(), async_read(), async_delete()
198+ - **Transactions **: async_run_in_transaction() context manager
199+ - **Context Managers **: async_switch_db(), async_switch_collection()
200+ - **Aggregation **: async_aggregate(), async_distinct()
201+ - **Cascade Operations **: Full support for all delete rules (CASCADE, NULLIFY, etc.)
202+
203+ **Current Limitations: **
204+
205+ The following features are intentionally not implemented due to low priority or complexity:
206+
207+ - **async_values() **, **async_values_list() **: Field projection methods
208+
209+ *Reason *: Low usage frequency in typical applications. Can be implemented if needed.
210+
211+ - **async_explain() **: Query execution plan analysis
212+
213+ *Reason *: Debugging/optimization feature with limited general use.
214+
215+ - **Hybrid Signal System **: Automatic sync/async signal handling
216+
217+ *Reason *: High complexity due to backward compatibility requirements.
218+ Consider as separate project if needed.
219+
220+ - **ListField with ReferenceField **: Automatic AsyncReferenceProxy conversion
221+
222+ *Reason *: Complex implementation requiring deep changes to ListField.
223+ Manual async dereferencing is required for now.
224+
225+ **Migration Guide: **
226+
227+ - Use ``connect_async() `` instead of ``connect() ``
228+ - Add ``async_ `` prefix to all database operations: ``save() `` → ``async_save() ``
229+ - Use ``async for `` for QuerySet iteration
230+ - Explicitly fetch references with ``await ref.async_fetch() `` in async context
231+ - Existing synchronous code remains 100% compatible when using ``connect() ``
161232
162233Tests
163234=====
0 commit comments