问题描述
我的mongoDB中有一个集合,其中存储了提供给客户的服务以及他们的电子邮件地址,如下所示:
I have collection in my mongoDB which stores service given to customer along with their email address something like below
{
"_id" : ObjectId("56a84627f8fd4a136c0e944a"),
"Vehicle" : "Honda",
"ServiceSelected" : "FULL SERVICE",
"FullName" : "xyz",
"Email" : "[email protected]",
"BookingTime" : ISODate("2015-12-27T06:00:00.000Z")
},
{
"_id" : ObjectId("56a84627f8fd4a136c0e944b"),
"Vehicle" : "AUDI",
"ServiceSelected" : "FLAT TYRE",
"FullName" : "abc",
"Email" : "[email protected]",
"BookingTime" : ISODate("2015-12-26T06:00:00.000Z")
},
{
"_id" : ObjectId("56a84627f8fd4a136c0e944c"),
"Vehicle" : "BMW",
"ServiceSelected" : "OTHERS",
"FullName" : "def",
"Email" : "[email protected]",
"BookingTime" : ISODate("2015-12-25T06:00:00.000Z")
},
{
"_id" : ObjectId("56a84627f8fd4a136c0e944d"),
"Vehicle" : "BMW",
"ServiceSelected" : "OTHERS",
"FullName" : "def",
"Email" : "[email protected]",
"BookingTime" : ISODate("2015-12-30T06:00:00.000Z")
},
{
"_id" : ObjectId("56a84627f8fd4a136c0e944a"),
"Vehicle" : "Honda",
"ServiceSelected" : "FULL SERVICE",
"FullName" : "xyz",
"Email" : "[email protected]",
"BookingTime" : ISODate("2016-01-27T06:00:00.000Z")
}
我要从上述集合中获取所有已使用我们服务的文档,至少要间隔30天,即应从以上集合电子邮件"中返回:"[email protected]",但不应返回电子邮件":"[email protected]",因为第二个服务是在5天内获得的.
From the above collection I want to fetch all the documents that have taken our service with a gap of at-least 30 days i.e. from the above collection "Email" : "[email protected]" should be returned but not "Email" : "[email protected]" as the second service was taken with in 5 days.
我知道设计存在缺陷,可以在从应用程序插入记录时设置其他标志,但是我需要获取现有记录的数据.
I know there is flaw in the design and an additional flag can be set while inserting the record from the application but I need to fetch the data for the existing records.
推荐答案
您需要使用 $min
和 $max
运算符,它们分别在您的 $group
阶段.管道的最后一个阶段是 $redact
使用 $divide
和 $subtract
算术运算符.返回第一个服务"到最后一个服务"之间的天数大于30的那些文档.
You need to use the $min
and $max
operators which respectively return the minimum and maximum value for "BookingTime" in your $group
stage. The last stage in the pipeline is the $redact
stage where you use a simple "date" math using the $divide
and $subtract
arithmetic operators.to return those documents where the number of days between first "service" and last "service" is greater than 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" : "[email protected]",
"date1" : ISODate("2015-12-27T06:00:00Z"),
"date2" : ISODate("2016-01-27T06:00:00Z")
}
另一种方法是使用 $cond
运算符在$project
阶段可避免进行集合扫描.
Another way to do this is by using the $cond
operator in a $project
stage to avoid a collection scan.
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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!