多个文档之间的MongoDB dateDiff

标签 mongodb date mongodb-query aggregation-framework

我在我的 mongoDB 中有一个集合,它存储提供给客户的服务以及他们的电子邮件地址,如下所示

{
    "_id" : ObjectId("56a84627f8fd4a136c0e944a"),    
    "Vehicle" : "Honda",
    "ServiceSelected" : "FULL SERVICE",
    "FullName" : "xyz",
    "Email" : "xyz@xyz.com",    
    "BookingTime" : ISODate("2015-12-27T06:00:00.000Z")
},

{
    "_id" : ObjectId("56a84627f8fd4a136c0e944b"),    
    "Vehicle" : "AUDI",
    "ServiceSelected" : "FLAT TYRE",
    "FullName" : "abc",
    "Email" : "abc@abc.com",    
    "BookingTime" : ISODate("2015-12-26T06:00:00.000Z")
},

{
    "_id" : ObjectId("56a84627f8fd4a136c0e944c"),    
    "Vehicle" : "BMW",
    "ServiceSelected" : "OTHERS",
    "FullName" : "def",
    "Email" : "def@def.com",    
    "BookingTime" : ISODate("2015-12-25T06:00:00.000Z")
},

{
    "_id" : ObjectId("56a84627f8fd4a136c0e944d"),    
    "Vehicle" : "BMW",
    "ServiceSelected" : "OTHERS",
    "FullName" : "def",
    "Email" : "def@def.com",    
    "BookingTime" : ISODate("2015-12-30T06:00:00.000Z")
},

{
    "_id" : ObjectId("56a84627f8fd4a136c0e944a"),    
    "Vehicle" : "Honda",
    "ServiceSelected" : "FULL SERVICE",
    "FullName" : "xyz",
    "Email" : "xyz@xyz.com",    
    "BookingTime" : ISODate("2016-01-27T06:00:00.000Z")
}

我想从上面的集合中获取至少间隔 30 天的所有文档,即从上面的集合中“电子邮件”:“xyz@xyz.com”应该返回但不是“电子邮件”:“def@def.com”,因为在 5 天内接受了第二次服务。

我知道设计存在缺陷,可以在从应用程序插入记录时设置一个额外的标志,但我需要为现有记录获取数据。

最佳答案

您需要使用 $min$max分别返回 $group 中“BookingTime”的最小值和最大值的运算符阶段。管道的最后阶段是 $redact使用 $divide 使用简单的“日期”数学的阶段和 $subtract算术运算符。返回第一个“服务”和最后一个“服务”之间的天数大于 30 的文档

db.collection.aggregate( [ 
    { "$group": { 
        "_id": "$Email",  
        "date1": { "$min": "$BookingTime" }, 
        "date2": { "$max": "$BookingTime" } 
    }}, 
    { "$redact": { 
        "$cond": [ 
             { "$gte": [ 
                 { "$divide": [ 
                     { "$subtract": [ "$date2", "$date1" ] }, 
                     1000 * 60 * 60 * 24 
                 ]}, 
                 30 
             ]}, 
             "$$KEEP", 
             "$$PRUNE" 
        ] 
    }}
])

哪个返回:

{
        "_id" : "xyz@xyz.com",
        "date1" : ISODate("2015-12-27T06:00:00Z"),
        "date2" : ISODate("2016-01-27T06:00:00Z")
}

另一种方法是使用 $cond $project 阶段中的运算符以避免集合扫描。

db.collection.aggregate( [ 
    { "$group": { 
        "_id": "$Email", 
        "date1": { "$min": "$BookingTime" },
        "date2": { "$max": "$BookingTime" }, 
        "count": { "$sum": 1 } 
    }},
    { "$match": { "count": { "$gte": 2 } } }, 
    { "$project": { 
        "emails": { 
            "$cond": [ 
                { "$gte": [ 
                    { "$divide": [ 
                        { "$subtract": [ "$date2", "$date1" ] }, 
                        1000 * 60 * 60 * 24 
                    ]}, 
                    30 
                ] }, 
                "$_id", 
                false 
            ] 
        } 
    }}, 
    { "$match": { "emails": { "$ne": false } } } 
])

关于多个文档之间的MongoDB dateDiff,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35055073/

相关文章:

mongodb - 对不同集合的两个查询 - MongoDB

mongodb - 如何正确创建索引mongodb?

mongodb - 仅检索 MongoDB 集合中对象数组中的查询元素

node.js - 范围错误: Maximum call stack size exceeded with mongoose

java - Mongodb- java 函数 com.mongodb.util.JSON.parse()

php - 存储当前日期时,应该在 web 应用程序中设置还是在数据库中设置?

javascript - 如何使用过滤器以 Angular 显示日期

mongodb - 无法使用 mongorestore 命令导入 mongodump

ruby - 关于链接多个 any_of 标准的问题#Mongoid

php - 如何使用时间戳从mysql中选择数据