Mongoose 按字段分组和分组结果应存储为 groupname: object

end*_*end 3 mongoose mongodb

对于以下 Schema(伪代码)。

new mongoose.Schema({
      name: {type: String, unique: true},
      foo: {type: Number},
      bar: {type: Number, default: null},
}
Run Code Online (Sandbox Code Playgroud)

正常结果是.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
}];
Run Code Online (Sandbox Code Playgroud)

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

[{
    '1': [{
        name: 'Name1'
        bar: 222
    }, {
        name: 'Name2'
        bar: 333
    }],
    '2': [{
        name: 'Name3'
        bar: 444
    }]
}]
Run Code Online (Sandbox Code Playgroud)

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

对于猫鼬来说这可能吗?或者我需要在 Nodejs 函数中编辑对象吗?

mic*_*ckl 8

您可以尝试以下聚合:

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" }
                }
            }
        }
    }
])
Run Code Online (Sandbox Code Playgroud)

输出:

{ "2" : [ { "name" : "Name3", "bar" : 444 } ] }
{ "1" : [ { "name" : "Name1", "bar" : 222 }, { "name" : "Name2", "bar" : 333 } ] }
Run Code Online (Sandbox Code Playgroud)

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