javascript - Mongoose,将 `.aggregate()` 应用于子文档数组,并以最少的查询次数获得文档其他字段的结果

标签 javascript node.js mongodb mongoose aggregation-framework

这是我的 Mongoose 模型:

const postSchema = new Schema({
    user: {
        type: Schema.Types.ObjectId,
        ref: 'User',
        required: true
    },

    caption: {
        type: String
    },

    action: {
        type: [{
            actionName: {
                type: String,
                required: true
            },
            user: {
                type: Schema.Types.ObjectId,
                ref: 'User'
            }
        }],
        default: []
    },

    shares: [{
        type: Schema.Types.ObjectId,
        ref: 'User'
    }];
});

我想要的是使用或不使用 .aggregate() 进行 mongodb 查询以获取 user & caption 字段是但不是 actionshares 我想要他们对特定文档的计数。

示例文档

{
    _id: "fgsergehegoieofgesfglesfg",

    user: "dfjksjdnfkjsdfkjsdklfjglkbj",

    caption: "This is the post caption",

    action: [
        {
            actionName: 'e1', user: "sdfasdsdfasdfdsdfac951e5c"
        },
        {
            actionName: 'e1', user: "asdfmadfadfee103c9c951e5d"
        },
        {
            actionName: 'e2', user: "op34937cdbae0cd4160bbec"
        },
        {
            actionName: 'e2', user: "2543ebbasdfd1750690b5b01c"
        },
        {
            actionName: 'e3', user: "asdfcfebdb5dd1750690b5b01d"
        },
    ],

    shares: ["ewrebdb5ddadsf5069sadf1d", "asdfsdfbb85dd1750690b5b01c", "fasec92dsfasde103c9c95df5d"]
};

查询后期望的输出:

{
    _id: "fgsergehegoieofgesfglesfg",
    user: 'dfjksjdnfkjsdfkjsdklfjglkbj',
    caption: 'This is the post caption',
    actionCount: [{ count: 1, actionName: 'e3' },
                 { count: 2, actionName: 'e2' },
                 { count: 2, actionName: 'e1' }],
    shareCount: 3
}

我能够使用 .aggregate() 获得以下结果:

查询:

let data = await Test.aggregate([
            { $match: { _id: mongoose.Types.ObjectId("fgsergehegoieofgesfglesfg") } },
            { $unwind: "$action" },
            {
                $group: {
                    _id: "$action.actionName",
                    count: { $sum: 1 }
                }
            },
            {
                $project: {
                    _id: 0,
                    actionName: "$_id",
                    count: 1
                }
            }
        ]);

结果:

[
  { count: 1, actionName: 'e3' },
  { count: 2, actionName: 'e2' },
  { count: 2, actionName: 'e1' } 
]

我只是想把这个放在原始文档中并得到结果。此外,对 share 字段执行相同的操作。如果这可以在单个查询中完成,那就更好了。我曾尝试将 $replaceRoot$mergeObjects 一起使用,但不知道如何正确使用它们。我对 mongodb 和 mongoose 很陌生。

请帮忙。谢谢。

最佳答案

由于您要聚合嵌套数组,因此需要运行 $group 两次,并且 $first 可用于保留原始文档的字段值:

await Test.aggregate([
    { $match: { _id: mongoose.Types.ObjectId("fgsergehegoieofgesfglesfg") } },
    { $unwind: "$action" },
    {
        $group: {
            _id: { _id: "$_id", actionName: "$action.actionName" },
            user: { $first: "$user" },
            caption: { $first: "$caption" },
            count: { $sum: 1 },
            shareCount: { $first: { $size: "$shares" } }
        }
    },
    {
        $group: {
            _id: "$_id._id",
            user: { $first: "$user" },
            caption: { $first: "$caption" },
            shareCount: { $first: "$shareCount" },
            actionCount: {
                $push: {
                    actionName: "$_id.actionName",
                    count: "$count"
                }
            }
        }
    }
])

Mongo Playground

关于javascript - Mongoose,将 `.aggregate()` 应用于子文档数组,并以最少的查询次数获得文档其他字段的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62972482/

相关文章:

javascript - 无法捕获 Bootstrap 3.3.6 关闭模态事件

javascript - 如何知道 JqGrid 多选 'select all' 复选框被选中

javascript - Mongoose 更新多个文档上的嵌套对象

mongodb - 查找具有仅包含特定值而不包含其他值的数组字段的文档

javascript - React Native 深层链接应用程序从后台打开

javascript - 将参数传递给 React JS 中的另一个页面

node.js - 在不同主机上建立套接字连接时出现 'ECONNREFUSED' 错误

javascript - 无法监听 Dsektop 窗口的默认关闭按钮

mysql - Node.js mySQL 模块错误

java - 在 mongodb java 中按日期和标签搜索