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

Ram*_*san 3 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"
    }
Run Code Online (Sandbox Code Playgroud)

如果我排序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)
            }
        ]
    }
Run Code Online (Sandbox Code Playgroud)

但是我想重新排列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"
    }
Run Code Online (Sandbox Code Playgroud)

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

Bla*_*ven 6

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

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

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

它使用了$project$sort聚集pipline阶段得到的结果所需的顺序.首先,$ifNull根据存在的数据决定将什么放置在投影文档的"sortfield"属性中,然后在$sort聚合管道阶段中使用该值.

您还可以在$match管道开始时将常规查询操作与管道阶段集成,建议减少在$project阶段中处理的文档.

对于不包含必填字段的文档,"sortfield"的值将高于预期值,并且这些文档将显示在结尾而不是开头.