Python 3.x Flask Mongoengine比较器定制订单

Python 3.x Flask Mongoengine比较器定制订单,python-3.x,mongoengine,flask-mongoengine,Python 3.x,Mongoengine,Flask Mongoengine,我正在使用Flask Mongoengine作为我的Flask应用程序的ORM。我定义了一个文档,以在字符串中存储唯一的版本: MyDocument(db.Document): version = db.StringField(primary_key=True, required=True) StringField中存储的值采用以下格式: a.b.c.d 在使用order\u by进行查询时,我遇到了一些问题: MyDocument.objects.order_by('version

我正在使用Flask Mongoengine作为我的Flask应用程序的ORM。我定义了一个
文档
,以在字符串中存储唯一的版本:

MyDocument(db.Document):
    version = db.StringField(primary_key=True, required=True)
StringField
中存储的值采用以下格式:

a.b.c.d
在使用
order\u by
进行查询时,我遇到了一些问题:

MyDocument.objects.order_by('version')
更准确地说,如果版本的第一部分(
a
在上面的格式示例中)包含多个数字,则它不能正确排序(例如:
15.20.142
1.7.9
)。当然我可以做一些事情,比如:

tmp = Document.objects.all()
result = some_merge_sort(tmp)
然而,这需要编写、测试和维护排序算法。这就引出了我的下一个解决方案,即用覆盖
order\u中使用的比较器。问题是,我不知道如何正确地做到这一点。我是否必须定义一个自定义属性类型,或者是否应该覆盖某个钩子


无论如何,在我开始重新编写轮子之前,我想我会像stackoverflow上的好人一样。

在深入研究了
Mongoengine
源代码之后,我发现它使用了
PyMongo
光标
排序
,它本身包装了对
MongoDB
的查询。换句话说,我的
文档
定义在链中的位置太高,甚至无法通过
结果影响
订单

因此,我采用的解决方案是编写一个
classmethod
。这只是接收一个
mongoengine.queryset.queryset
实例,并对
version
属性应用排序

from mongoengine.queryset import QuerySet
from packaging import version

class MyDocument(db.Document):
    version = db.StringField(primary_key=True, required=True)

    @classmethod
    def order_by_version(_, queryset, reverse=False):
        """
            Wrapper function to order a given queryset of this classes
            version attribute.

            :params:
                - `QuerySet` :queryset: - The queryset to order the elements.
                - `bool`     :reverse:  - If the results should be reversed.

            :raises:
                - `TypeError` if the instance of the given queryset is not a `QuerySet`.

            :returns:
                - `List` containing the elements sorted by the version attribute.
       """
       # Instance check the queryset.
       if not isinstance(queryset, QuerySet):
           raise TypeError("order_by_version requires a QuerySet instance!")

       # Sort by the version attribute.
       return sorted(queryset, key=lambda obj: version.parse(obj.version), reverse=reverse)
然后,为了使用此方法,我可以简单地执行以下操作:

MyDocument.order_by_version(MyDocument.objects)

至于我选择
QuerySet
实例而不是从classmethod中进行查询的原因,只是为了在进行排序之前允许调用其他
Mongoengine
方法。因为我使用了
sorted
,它将维护任何现有的订单,所以我仍然可以使用内置的
order\u by
作为其他属性。

嘿,谢谢你的详细问题。您是否也可以添加一段您现在拥有的代码,理想情况下是易于复制的?这将有助于其他人给你量身定制的答案。@NickShebanov我已经添加了相关的代码片段。