将没有现有字段的文档排序到结果的结尾

时间:2015-10-22 07:52:29

标签: mongodb mongodb-query aggregation-framework

我有以下文件,很少有文件只有bids个字段。

收集:

   { 
        "_id" : "PqwSsLb2jsqTycMWR", 
        "name" : "aaa", 
        "bids" : [
            {
                "amount" : NumberInt(450)
            }
        ]
    }
    { 
        "_id" : "93EDoQfeYEFk8pyzX", 
        "name" : "bbb"
    }
    { 
        "_id" : "j5wkK5Eagnwuo8Jym", 
        "name" : "ccc", 
        "bids" : [
            {
                "amount" : NumberInt(520)
            }
        ]
    }
    { 
        "_id" : "eLaTyM5h5kqA97WQQ", 
        "name" : "ddd"
    }

如果我按bids.amount : 1排序结果

结果:

   { 
       "_id" : "93EDoQfeYEFk8pyzX", 
       "name" : "bbb"
   }
   { 
       "_id" : "eLaTyM5h5kqA97WQQ", 
       "name" : "ddd"
   }
   { 
        "_id" : "PqwSsLb2jsqTycMWR", 
        "name" : "aaa", 
        "bids" : [
            {
                "amount" : NumberInt(450)
            }
        ]
    }
    { 
        "_id" : "j5wkK5Eagnwuo8Jym", 
        "name" : "ccc", 
        "bids" : [
            {
                "amount" : NumberInt(520)
            }
        ]
    }

但我想重新排列bid.amount应该位于顶部的订单。

预期结果:

   { 
        "_id" : "PqwSsLb2jsqTycMWR", 
        "name" : "aaa", 
        "bids" : [
            {
                "amount" : NumberInt(450)
            }
        ]
    }
    { 
        "_id" : "j5wkK5Eagnwuo8Jym", 
        "name" : "ccc", 
        "bids" : [
            {
                "amount" : NumberInt(520)
            }
        ]
    }
    { 
        "_id" : "93EDoQfeYEFk8pyzX", 
        "name" : "bbb"
    }
    { 
        "_id" : "eLaTyM5h5kqA97WQQ", 
        "name" : "ddd"
    }

查询是什么获得预期结果?

1 个答案:

答案 0 :(得分:6)

由于您指定了.sort()中所有文档中不存在的字段,因此不存在该字段时,该值被视为null,这当然是较低的顺序,因此较高排序结果中的优先级高于任何其他值。

可以改变响应的唯一方法是基本上“投射”一个比其他预期值范围更高的值,以便那些结果落到其他结果的末尾。具有预计值的此类“加权”查询需要使用.aggregate()方法:

db.collection.aggregate([
    { "$project": {
        "name": 1,
        "bids": 1,
        "sortfield": { "$ifNull": [ "$bids", 999999 ] }
    }},
    { "$sort": { "sortfield": 1 } }
])

这使用$project$sort聚合pipline阶段以所需顺序获取结果。首先使用$ifNull操作来决定在预测文档的“sortfield”属性中放置什么,具体取决于存在的数据,然后在$sort聚合管道阶段中使用该值。

您还可以在管道开始时将普通查询操作与$match管道阶段集成,建议减少需要在$project阶段处理的文档。

如果文档中不包含必填字段,则“sortfield”的值将高于预期值,这些文档将显示在结尾而不是开头。