首页 > 解决方案 > Mongoose 按字段分组和分组结果应存储为 groupname: object

问题描述

对于以下 Schema(伪代码)。

new mongoose.Schema({
      name: {type: String, unique: true},
      foo: {type: Number},
      bar: {type: Number, default: null},
}

正常结果是 .find():

[{
    _id: x
    name: 'Name1'
    foo: 1
    bar: 222
}, {
    _id: y
    name: 'Name2'
    foo: 1
    bar: 333
}, {
    _id: z
    name: 'Name3'
    foo: 2
    bar: 444
}];

我想返回按 foo 分组的结果,键应该是 foo 的变量/数量:

[{
    '1': [{
        name: 'Name1'
        bar: 222
    }, {
        name: 'Name2'
        bar: 333
    }],
    '2': [{
        name: 'Name3'
        bar: 444
    }]
}]

我正在尝试使用聚合,但我永远无法将 _id 替换为“Foo 的数量”。

猫鼬甚至可以做到这一点吗?还是我需要在 Nodejs 函数中编辑对象?

标签: mongodbmongoose

解决方案


您可以尝试以下聚合:

db.col.aggregate([
    {
        $group: {
            _id: "$foo",
            obj: { $push: { name: "$name", bar: "$bar" } }
        }
    },
    {
        $replaceRoot: {
            newRoot: {
                $let: {
                    vars: { obj: [ { k: {$substr:["$_id", 0, -1 ]}, v: "$obj" } ] },
                    in: { $arrayToObject: "$$obj" }
                }
            }
        }
    }
])

输出:

{ "2" : [ { "name" : "Name3", "bar" : 444 } ] }
{ "1" : [ { "name" : "Name1", "bar" : 222 }, { "name" : "Name2", "bar" : 333 } ] }

$replaceRoot允许您在根级别定义新对象。要动态创建密钥,您需要$arrayToObject,它采用 kv 对数组(在此处使用$let定义)。要将 int 转换为字符串,您可以在 MongoDB v 4.0 中使用( ) 或$toString运算符的技巧$substr{$substr:["$foo", 0, -1 ]}


推荐阅读