When using select_related() with async QuerySets in MongoEngine, a TypeError: 'AsyncCursor' object is not an iterator error occurs because the synchronous select_related() method tries to iterate over an AsyncCursor using synchronous iteration.
We've implemented a new async_select_related() method that properly handles async cursors and dereferences.
- New Method:
async_select_related(max_depth=1)inBaseQuerySet - New Class:
AsyncDeReferenceinmongoengine/dereference.pythat handles async operations - New Method:
async_in_bulk(object_ids)for efficient bulk fetching in async context
Instead of:
# This will fail with TypeError
items = await self.skip(skip).limit(limit + 1).select_related().async_to_list()Use:
# This works correctly
items = await self.skip(skip).limit(limit + 1).async_select_related()from mongoengine import Document, ReferenceField, StringField, connect_async
class Author(Document):
name = StringField(required=True)
class Post(Document):
title = StringField(required=True)
author = ReferenceField(Author)
class Comment(Document):
content = StringField(required=True)
post = ReferenceField(Post)
author = ReferenceField(Author)
# Connect to async MongoDB
await connect_async('mydb')
# Create data
author = Author(name="John Doe")
await author.async_save()
post = Post(title="Hello World", author=author)
await post.async_save()
# Query with select_related
posts = await Post.objects.async_select_related()
# posts[0].author is now the actual Author document, not a reference
# With nested references (max_depth=2)
comments = await Comment.objects.async_select_related(max_depth=2)
# comments[0].post and comments[0].author are dereferenced
# Note: comments[0].post.author remains an AsyncReferenceProxy-
Nested References: With
max_depth > 1, deeply nested references may still beAsyncReferenceProxyobjects that require explicit fetching:# For deeply nested references author = await comment.post.author.fetch()
-
Performance: Like the sync version,
async_select_related()performs additional queries to fetch all referenced documents. Use it when you know you'll need the referenced data.
If you're migrating from synchronous to asynchronous MongoEngine:
- Replace
select_related()withasync_select_related() - Replace
in_bulk()withasync_in_bulk()if used directly - Be aware that async operations return
AsyncReferenceProxyfor references by default
The implementation includes comprehensive tests in tests/test_async_select_related.py covering:
- Single reference dereferencing
- Multiple reference fields
- Filtering with select_related
- Skip/limit with select_related
- Empty querysets
- Max depth handling