Python 3.x Flask Mongoengine比较器定制订单
我正在使用Flask Mongoengine作为我的Flask应用程序的ORM。我定义了一个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
文档
,以在字符串中存储唯一的版本:
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我已经添加了相关的代码片段。