如何修复 $sort 不适用于 mongoDB 中数组内的数组?

How to fix $sort is not working for array inside array in mongoDB?

我的文档如下:

{
    "_id" : ObjectId("622136811b68d9136e48ba4e"),
    "brand_name" : "iPhone",
    "brand_rating" : [
        {
            "cust_name" : "Sham K",
            "rating" : 5
        },
        {
            "cust_name" : "Nil",
            "rating" : 5
        }
    ],
    "models" : [
        {
            "model_name" : "iPhone 7Plus",
            "RAM" : "4GB",
            "ROM" : "64GB",
            "price" : 98000,
            "buyer" : [
                {
                    "cust_name" : "Anu",
                    "rating" : 3
                },
                {
                    "cust_name" : "Kiran",
                    "rating" : 4
                }
            ]
        },
        {
            "model_name" : "iPhone 2",
            "RAM" : "3GB",
            "ROM" : "32GB",
            "price" : 58000,
            "buyer" : [
                {
                    "cust_name" : "Kiran",
                    "rating" : 4
                }
            ]
        }
    ]
}

问题是 按降序列出购买了 iPhone 7plus 的所有客户。

我试过了,但排序不起作用

db.brand.aggregate({$unwind : "$models"},{$match : {"models.model_name" :"iPhone 7Plus" }}, {$project : {_id : 0, "models.buyer.cust_name" : 1}}, {$sort : {"models.buyer.cust_name" : -1} })

输出:

    { "models" : { "buyer" : [ { "cust_name" : "Anu" }, { "cust_name" : "Kiran" } ] } }

> [5]

最简单的解决方法是什么?

$sort

之前$unwind怎么样
db.collection.aggregate({
  $unwind: "$models"
},
{
  $match: {
    "models.model_name": "iPhone 7Plus"
  }
},
{
  $project: {
    _id: 0,
    "models.buyer.cust_name": 1
  }
},
{
  $unwind: "$models.buyer"
},
{
  $sort: {
    "models.buyer.cust_name": -1
  }
})

mongoplayground

这是一个只有 3 个阶段的变体,单个 $unwind 被尽可能“向下”推入管道,以尽量减少文档的数量和大小。此变体中的关键是使用 $filter 后跟点符号表达式来获取我们想要的数据,而不必过早使用 $unwind

db.foo.aggregate([
    {$project: {
        _id:false,
        cust_name:
        // Explaining this "inside out":                                             
        // 1.  Start by filtering the models array for iphone 7plus.              
        //     This will yield an array of 1 item (or zero).                      
        // 2.  We want to get the cust_name from buyer array.  Use                
        //     $map on the array of 1 to extract the names using the              
        //     dot notation trick buyer.cust_name to create an array              
        //     of just names.                                                     
        // 3.  We have that list -- but it is a list inside the array             
        //     of one, e.g. [ [ name1, name2 ] ] .  So we lift out                
        //     the inner array with $arrayElemAt: [ inner, 0 ].
        //     Note: v>=4.4 you can use $first: { inner } as a convenient
        //     substitute for $arrayElemAt: [ inner, 0 ]                 
            {$arrayElemAt: [
                {$map: {
                    input: {$filter: {
                      input: "$models",
                      cond: {$eq:['$$this.model_name','iPhone 7Plus']}
                    }},
                    in: "$$this.buyer.cust_name"
                }}, 0]
            }
       }}

    // At this stage we have:                                                     
    // { "cust_name" : [ "Anu", "Kiran" ] }                                       
    // Now it's easy:                                                             
    ,{$unwind: '$cust_name'}
    ,{$sort: {'cust_name':-1}}
]);