Mongoengine中的"QuerySet"对象到底是什么?

13 投票
1 回答
10109 浏览
提问于 2025-04-17 17:32

根据Mongoengine的API指南(http://mongoengine-odm.readthedocs.org/en/latest/apireference.html),

class mongoengine.queryset.QuerySet(document, collection)

它的意思是“从查询中返回的一组结果。它封装了一个MongoDB的游标,提供文档对象作为结果。”

当我在我的解释器中使用type()检查QuerySet对象时,它显示这个对象是<class 'mongoengine.queryset.QuerySet'>,这和API指南说的一样。

不过我有点困惑,因为要想真正访问QuerySet实例中的单个Mongoengine Document对象,我必须使用像[0](表示第一个Document对象)或[2](表示第三个Document对象)这样的索引方法。可以查看这个关于切片QuerySet的StackOverflow问题。有趣的是,你也可以对QuerySet实例调用len()

尽管QuerySet是一个类对象,但为什么它看起来像一个列表对象呢?据我所知,它并没有继承UserList,也没有data属性。任何帮助都非常感谢。

谢谢。

编辑:

感谢你的建议@isbadawi。这很有帮助。QuerySet类对象确实包含__getitem__方法,正如你链接中提到的,它“基本上等同于”索引(例如,x.__getitem__(i)大致等同于x[i])。所以如果QuerySet是通过__getitem__模拟一个列表类,那么实际的Document对象是存储在哪里的呢?是在某个属性中吗?这是我在解释器中运行dir(QuerySet)的输出:

> ['_QuerySet__already_indexed', '_QuerySet__dereference', '__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__getitem__', '__hash__', '__init__', '__iter__', '__len__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_as_pymongo', '_as_pymongo_coerce', '_build_index_spec', '_class_check', '_collection', '_collection_obj', '_cursor', '_cursor_args', '_cursor_obj', '_dereference', '_document', '_ensure_indexes', '_fields_to_dbfields', '_get_as_pymongo', '_get_scalar', '_hint', '_initial_query', '_item_frequencies_exec_js', '_item_frequencies_map_reduce', '_iter', '_limit', '_loaded_fields', '_lookup_field', '_mongo_query', '_ordering', '_query', '_query_obj', '_reset_already_indexed', '_scalar', '_skip', '_slave_okay', '_snapshot', '_sub_js_fields', '_timeout', '_transform_query', '_transform_update', '_translate_field_name', '_where_clause', 'all', 'all_fields', 'as_pymongo', 'average', 'clone', 'count', 'create', 'delete', 'distinct', 'ensure_index', 'exclude', 'exec_js', 'explain', 'fields', 'filter', 'first', 'get', 'get_or_create', 'hint', 'in_bulk', 'insert', 'item_frequencies', 'limit', 'map_reduce', 'next', 'only', 'order_by', 'rewind', 'scalar', 'select_related', 'skip', 'slave_okay', 'snapshot', 'sum', 'timeout', 'update', 'update_one', 'values_list', 'where', 'with_id']

1 个回答

8

这段代码中,QuerySet 是对 pymongo 的 cursor 的一种抽象,也就是说,QuerySet 本身并不存储数据。

当你调用 len() 时,其实是触发了 QuerySet.__len__ 这个特殊的方法,它会返回 self.count() 的结果,也就是从游标那里获取数据的数量。

其他的操作也是类似的。比如,QuerySet.__getitem__ 会向游标请求对应的项,而 QuerySet.first 也是做同样的事情。

如果你对内部实现有疑问,我强烈建议你查看一下代码。

撰写回答