heynemann / motorengine

Motorengine is a port of MongoEngine for Tornado.
http://motorengine.readthedocs.org
204 stars 67 forks source link

cannot execute find_all and count on a queryset serially #93

Closed wonderbeyond closed 6 years ago

wonderbeyond commented 9 years ago

Here is my handler method:

    @tornado.web.asynchronous
    @tornado.gen.coroutine
    def get(self):
        qs = self.filter_queryset()
        rs, count = yield [qs.find_all(), qs.count()]

        self.write({
            'page': self.page,
            'page_size': self.page_size,
            'count': count,
            'result': [dict((k, getattr(p, k)) for k in self.asking_fields)
                       for p in rs]
        })

I just want to get the result and the count at the same time. However, the qs.count() just get the total number of the records in db, not in my qs.

I've looked into motorengine source code, foud that qs.find_all() would clean the queryset's internal filter state after self use.

len(rs) is also not what I want, because I've done skip and limit on the queryset(in filter_queryset method).

Any helps? many thanks!

heynemann commented 9 years ago

As a workaround:

qs = self.filter_queryset()
rs = yield qs.find_all()

qs = self.filter_queryset()
count = yield qs.count()

Remember that getting a queryset does not execute anything, so no performance penalty involved.

wonderbeyond commented 9 years ago

Many thanks to @heynemann.

A shallow copy of a queryset also works:

qs = self.filter_queryset()
rs, count = yield [copy.copy(qs).find_all(), copy.copy(qs).count()]

However, I don't think it's a good idea to clean the internal filter state alter done find_all or count implicitly, which may cause confusion.

heynemann commented 9 years ago

Do you think you can help with a Pull Request?