【问题标题】:Order_by length of listfield in mongoenginemongoengine中listfield的order_by长度
【发布时间】:2015-03-09 19:36:22
【问题描述】:

我不想运行查询来获取所有超过 6 个 com 的文章,然后根据 com 列表的长度进行排序, 为此,我这样做了:

 ArticleModel.objects.filter(com__6__exists=True).order_by('-com.length')[:50]                                                                  

假设 com 是一个 ListField,但排序不起作用,我该如何解决?谢谢

【问题讨论】:

    标签: mongodb python-2.7 mongodb-query aggregation-framework mongoengine


    【解决方案1】:

    标准查询无法做到这一点,因为“排序”需要在文档中存在的物理字段上完成。做到这一点的最好方法是实际将您的“列表”计数作为文档中的另一个字段。这也使您的查询更加高效,并且可以索引“计数器”字段,因此基本查询变为(原始 MongoDB 语法):

    { "comLength": { "$gt": 6 } }
    

    如果您不能或不想更改文档结构,那么按列表长度排序的唯一方法是通过.aggregate() $project 它:

    ArticleModel._get_collection().aggregate([
        { "$match": { "com.6": { "$exists": true } }},
        { "$project": {
            "com": 1,
            "otherField": 1,
            "comLength": { "$size": "$com" }
        }},
        { "$sort": { "comLength": -1 } }
    ])
    

    这认为您至少有 MongoDB 2.6 可以使用 $size 聚合运算符。如果不这样做,则必须 $unwind$group 才能计算数组的长度:

    ArticleModel._get_collection().aggregate([
        { "$match": { "com.6": { "$exists": true } }},
        { "$unwind": "$com" },
        { "$group": {
            "_id": "$_id",
            "otherField": { "$first": "$otherField" }
            "com": { "$push": "$com" },
            "comLength": { "$sum": 1 }
        }},
        { "$sort": { "comLength": -1 } }
    ])
    

    因此,如果您打算走这条路,那么请仔细查看文档,因为您可能不习惯原始的 MongoDB 语法,并且一直在使用 MongoEngine 提供的查询 DSL。

    总体而言,只有.aggregate().mapReduce() 中的聚合提供程序才能真正“创建文档中不存在的字段”。也没有测试可用于标准投影或文档排序的“当前”长度。

    添加另一个字段并使其与实际数组长度保持同步的最佳选择。但如果上述内容未能向您展示一般方法。

    【讨论】:

      【解决方案2】:

      如果您正在创建数据库并且您知道此类请求通常会被大量请求,建议在 A ArticleModel 中添加“com_length”字段,并使用 save() 方法使其在每次保存时自动插入

      在models.py中添加ArticleModel

       def save(self, *args, **kwargs):
          self.com_length = len(self.com)
          return super(ArticleModel, self).save(*args, **kwargs)
      

      然后请求提出的问题:

       ArticleModel.objects.filter(com__6__exists=True).order_by('-com_length')[:50]                                                                  
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-10-04
        • 1970-01-01
        • 2019-04-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多