【问题标题】:Find after aggregate in MongoDB在 MongoDB 中聚合后查找
【发布时间】:2017-09-22 04:13:51
【问题描述】:
{
    "_id" : ObjectId("5852725660632d916c8b9a38"),
    "response_log" : [ 
    {
        "campaignId" : "AA",
        "created_at" : ISODate("2016-12-20T11:53:55.727Z")
    }, 
    {
        "campaignId" : "AB",
        "created_at" : ISODate("2016-12-20T11:55:55.727Z")

    }]
}

我有一个包含数组的文档。我想从当前时间开始选择过去 2 小时内没有 response_log.created_at 的所有文档,并且过去 24 小时内 response_log.created_at 的计数小于 3。

我不知道该怎么做。请帮忙

【问题讨论】:

    标签: node.js mongodb mongodb-query aggregation-framework database


    【解决方案1】:

    您可以使用聚合框架来过滤文档。带有 $match$redact 步骤的管道将执行过滤。

    考虑运行以下聚合操作,其中 $redact 允许您使用 $cond 运算符处理逻辑条件并使用系统变量 @987654325 @“保留”逻辑条件为真的文档或$$PRUNE“删除”条件为假的文档。

    此操作类似于具有 $project 管道,该管道选择集合中的字段并创建一个新字段来保存逻辑条件查询的结果,然后是后续 @ 987654328@,除了 $redact 使用更高效的单个流水线阶段:

    var moment = require('moment'),
        last2hours = moment().subtract(2, 'hours').toDate(),
        last24hours = moment().subtract(24, 'hours').toDate();
    
    MongoClient.connect(config.database)
        .then(function(db) {
            return db.collection('MyCollection')
        })
        .then(function (collection) {
            return collection.aggregate([
                { '$match': { 'response_log.created_at': { '$gt': last2hours } } },
                { 
                    '$redact': {
                        '$cond': [
                            { 
                                '$lt': [
                                    {
                                        '$size': {
                                            '$filter': {
                                                'input': '$response_log',
                                                'as': 'res',
                                                'cond': { 
                                                    '$lt': [
                                                        '$$res.created_at', 
                                                        last24hours
                                                    ] 
                                                }
                                            }
                                        }
                                    },
                                    3
                                ]
                            },
                            '$$KEEP',
                            '$$PRUNE'
                        ]
                    }
                }
            ]).toArray();  
        })
        .then(function(docs) {
            console.log(docs)
        })
        .catch(function(err) {
            throw err;
        });
    

    说明

    在上述聚合操作中,如果执行第一个$match管道步骤

    collection.aggregate([
        { '$match': { 'response_log.created_at': { '$gt': last2hours } } }
    ])
    

    返回的文档将是从当前时间开始的最近 2 小时内没有 "response_log.created_at" 的文档,其中使用 subtract 使用 momentjs 库创建变量 last2hours API。


    前面带有 $redact 的管道将使用 $cond 三元运算符进一步过滤上面的文档,该三元运算符评估使用 的逻辑表达式>$size 获取计数,$filter 返回一个过滤后的数组,其中包含与其他逻辑条件匹配的元素

    { 
        '$lt': [
            {
                '$size': {
                    '$filter': {
                        'input': '$response_log',
                        'as': 'res',
                        'cond': { '$lt': ['$$res.created_at', last24hours] }
                    }
                }
            },
            3
        ]
    }
    
    如果条件为真,

    $$KEEP 文档或 $$PRUNE“删除”评估条件为假的文档。

    【讨论】:

    • 实际上只有解释中匹配的部分就足够了
    【解决方案2】:

    我知道这可能不是您正在寻找的答案,但这可能不是 Mongo 的最佳用例。在关系数据库中很容易做到这一点,在支持 map/reduce 的数据库中很容易做到这一点,但在 Mongo 中却不是那么简单。

    如果您的数据看起来不同,并且您将每个日志条目保存为引用该对象的单独文档(在本例中为 5852725660632d916c8b9a38)而不是它的一部分,那么您可以对最新的日志条目进行简单查询有那个id。如果我愿意为此使用 Mongo(我不会),这就是我在你的情况下会做的事情。

    您还可以在 Mongo 中保留一个单独的集合,或者向您在此处拥有的对象添加一个新属性,该属性将存储添加的活动的最新日期。然后就很容易找到你需要的东西了。

    当您使用像 Mongo 这样的数据库时,您的数据的外观必须反映您需要用它做什么,就像在这种情况下一样。添加最后一个广告系列日期并在添加的每个广告系列中更新它可以让您非常轻松地搜索您需要的广告系列。

    如果您希望能够进行任何搜索和聚合,那么最好使用关系数据库。

    【讨论】:

      猜你喜欢
      • 2020-04-14
      • 1970-01-01
      • 2017-05-05
      • 2017-07-19
      • 1970-01-01
      • 2022-01-03
      • 2017-11-08
      • 2020-06-29
      • 2019-01-17
      相关资源
      最近更新 更多