使用聚合在MongoDB中对嵌套数组进行排序

时间:2020-07-18 08:18:53

标签: arrays mongodb sorting nested

我正在尝试对嵌套数组“ subCategoryList进行排序,而不是在父文档上按_id进行排序。

以下是示例文档:

[
    {
        "_id": 1000,
        "name": "Automobiles",
        "parentId": "",
        "helpText": "Year, Brand, Model, Color, Size"
    },
    {
        "_id": 1004,
        "name": "RV / Campers",
        "parentId": 1000,
        "helpText": ""
    },
    {
        "_id": 1001,
        "name": "Car / SUV / Truck",
        "parentId": 1000,
        "helpText": ""
    }
]

这是我尝试过的:

db.Category.aggregate([
    {
        "$match": {
            "parentId": ""
        }
    },
    {
        "$lookup": {
            "from": "Category", "localField": "_id", "foreignField": "parentId", "as": "subCategoryList"
        }
    },
    {
        $sort: {
            _id: 1
        }
    }
]).pretty()

但是我得到了

    {
    "_id" : 17000,
    "name" : "Music",
    "parentId" : "",
    "helpText" : "Help Text - Brand, Model, Title",
    "subCategoryList" : [
        {
            "_id" : 17001,
            "name" : "DVD / Blu-ray",
            "parentId" : 17000,
            "helpText" : ""
        },
        {
            "_id" : 17002,
            "name" : "Player",
            "parentId" : 17000,
            "helpText" : ""
        }
    ]
}
{
    "_id" : 20000,
    "name" : "Sports Gear",
    "parentId" : "",
    "helpText" : "Help Text - Brand, Model, Gear Type, Size, Color,",
    "subCategoryList" : [
        {
            "_id" : 20002,
            "name" : "Football",
            "parentId" : 20000,
            "helpText" : ""
        },
        {
            "_id" : 20007,
            "name" : "Tennis",
            "parentId" : 20000,
            "helpText" : ""
        },
        {
            "_id" : 20008,
            "name" : "Cricket",
            "parentId" : 20000,
            "helpText" : ""
        },
        {
            "_id" : 20004,
            "name" : "Hockey",
            "parentId" : 20000,
            "helpText" : ""
        },
        {
            "_id" : 20003,
            "name" : "Golf",
            "parentId" : 20000,
            "helpText" : ""
        },
        {
            "_id" : 20006,
            "name" : "Basketball",
            "parentId" : 20000,
            "helpText" : ""
        },
        {
            "_id" : 20005,
            "name" : "Soccer",
            "parentId" : 20000,
            "helpText" : ""
        },
        {
            "_id" : 20010,
            "name" : "Camping / Hiking",
            "parentId" : 20000,
            "helpText" : ""
        },
        {
            "_id" : 20009,
            "name" : "Cycling",
            "parentId" : 20000,
            "helpText" : ""
        },
        {
            "_id" : 20001,
            "name" : "Baseball",
            "parentId" : 20000,
            "helpText" : ""
        },
        {
            "_id" : 20012,
            "name" : "Skiing",
            "parentId" : 20000,
            "helpText" : ""
        },
        {
            "_id" : 20011,
            "name" : "Swimming",
            "parentId" : 20000,
            "helpText" : ""
        },
        {
            "_id" : 20099,
            "name" : "Other",
            "parentId" : 20000,
            "helpText" : ""
        }
    ]
}

2 个答案:

答案 0 :(得分:0)

db.hardwares.aggregate([
    {$unwind: "$subCategoryList"},
    {$sort: {"subCategoryList._id": 1}},
    {$group: {_id:"$_id", subCategoryList: {$push:"$subCategoryList"}}}
]);

可能会对您有所帮助,请尝试这样... 可能是行不通,但它给出了一个主意

答案 1 :(得分:0)

Mongo没有用于对内部数组进行排序的内置函数,但是Mongo v4.4引入了$function聚合运算符。这使我们可以在管道中使用自定义javascript函数。

您可以这样使用它:

db.Category.aggregate([
    {
        $addFields: {
            "subCategoryList":
                {
                    $function: {
                        body: function (categories) {
                            return categories.sort((a, b) => a._id - b._id);
                        },
                        args: ["$subCategoryList"],
                        lang: "js"
                    }
                }
        }
    }
])

对于较小的Mongo版本,您必须首先$unwind阵列。然后$sort,最后构造原始结构,或者由于您正在$lookup构建内部数组,您可以使用v3.6引入的other $lookup语法$sort中的$lookup

db.Category.aggregate([
    {
        "$match": {
            "parentId": ""
        }
    },
    {
        "$lookup": {
            "from": "Category",
            let: {id: "$_id"},
            pipeline: [
                {
                    $match: {
                        $expr: {
                            $eq: ["$$id", "$parentId"]
                        }
                    }
                },
                {
                    $sort: {
                        _id: 1
                    }
                }
            ],
            "as": "subCategoryList"
        }
    },
    {
        $sort: {
            _id: 1
        }
    }
]);