【问题标题】:Mongoose count embed array elements with aggregateMongoose 计数使用聚合嵌入数组元素
【发布时间】:2019-04-19 20:50:12
【问题描述】:

我目前正在尝试实现一些在 SQL 中微不足道的东西,但对于 Mongoose/MongoDb 3.3 来说真的很痛苦。

我有一系列对话。对话由发行者开始,由零个或多个消息组成。消息在发行者和用户之间交换并存储在消息数组中。我的工作很简单,计算给定发布者的未读消息数。

一个发行人的单个对话可能如下所示:

{
    "_id" : ObjectId("578caba0264f76ec80d87e7c"),
    "issuer" : ObjectId("578c9c68261246f717343ab7"),
    "messages" : [
        {
            "content" : "Hi !",
            "type" : "text",
            "user" : ObjectId("56582b17b380912011c485e2"),
            "_id" : ObjectId("578caba08cf9a9081927e326"),
            "createdAt" : ISODate("2016-07-18T10:12:48.778Z"),
            "seenAt" : ISODate("2016-07-18T10:13:16.725Z")
        },
        {
            "content" : "Wassup ?",
            "type" : "text",
            "user" : ObjectId("569a9d343bd9840e26797412"),
            "_id" : ObjectId("578cabcb8cf9a9081927e327"),
            "createdAt" : ISODate("2016-07-18T10:13:31.254Z"),
            "seenAt" : ISODate("2016-07-18T10:13:34.133Z")
        },
        {
            "content" : "Fine, ya ?",
            "type" : "text",
            "user" : ObjectId("569a9d343bd9840e26797412"),
            "_id" : ObjectId("578cabd38cf9a9081927e328"),
            "createdAt" : ISODate("2016-07-18T10:13:39.573Z")
        }
    }
}

到目前为止,我尝试的是使用 Mongoose 聚合:

function findUnreadByIssuerId(issuerId) {
    return Conversation
    .aggregate()
    .match({ issuer: issuerId })
    .unwind('messages')
    .match({'messages.seenAt' : { $exists: 'false'} })
    .count()
    .exec();
}

这里的重点是 nodejs 抱怨 count() 不是一个函数。聚合似乎还可以,因为如果我删除 count() 我会得到一个数组。

然后,我尝试使用 $group,但我是 Mongo 及其分组的新手,我得到一个空数组:

return Conversation .aggregate([
    { $match: { issuer: issuerId } },
    { $unwind: '$messages' },
    { $match: {'messages.seenAt' : { $exists: 'false'} } },
    { $group: {
        _id: '$messages.createdAt',
        count: { $sum: 1 }
    }}
    ])
    .exec();

在提供的示例中,调用的预期结果理想情况下为 2。但我可以处理 { sum: 2} 虽然不理想。我的 Mongoose 聚合链有什么问题?

【问题讨论】:

    标签: node.js mongoose count aggregate


    【解决方案1】:

    对于 Mongo >= 3.4:

    您应该为 $count 提供一个参数,即 count 列的名称。

    https://docs.mongodb.com/manual/reference/operator/aggregation/count/

    像这样使用它:

    .count("total_unseen")

    它不是返回一个整数而是一个对象 {total_unseen: 1}

    对于 Mongo

    使用 $group 和计数:

    { $group: null, count: {$sum: 1} }
    

    关于结果: 如果管道中的某个阶段为空,则结果将为空,但通常驱动程序正在转换为更合适的值。

    所以对于这两种方法,当计数为 0 时,结果将为空数组或 null。 (取决于驱动程序)

    【讨论】:

    • 我需要坚持使用 MongoDb 3.3。 $count 从 MongoDb 3.4 开始可用。我相应地更新了问题。
    • 你的回答让我感到困惑的两件事:第一件事,结果是一个数组。第二个,如果没有消息包含 seenAt 字段,则结果是 [],而不是 [{count:0}]。关于如何获得一致的输出的任何想法?
    • 我最终将您的 Mongo
    猜你喜欢
    • 2021-08-04
    • 2018-09-17
    • 2017-02-17
    • 2017-01-20
    • 2017-04-24
    • 2021-10-10
    • 2016-05-28
    • 2021-06-15
    • 2020-11-09
    相关资源
    最近更新 更多