我不知道如何清楚地表达我的问题,但让我试着给予一个例子来解释我想做的事情。
顺便说一句,我是MongoDB的新手,来自SQL。
我需要查询一个集合,并检查特定日期字段expiryDate
福尔斯在今天,1个月前或3个月前。
我可以使用{ 'expiryDate':'2023-03-30' }
创建一个过滤器来检查今天过期的记录,这个过滤器返回在2023-03-30
过期的记录。
但是,我不知道如何获得那些在1个月前到期的记录(2023-02-28
)和3个月前到期的记录(2022-12-30
),因为存储在DB中的实际expiryDate
是2023-03-30
)。
如果我使用MySQL,我可以用DATE_ADD()
为expire1Month
和expire3Months
创建额外的字段。然后我可以过滤这些新字段,如果它福尔斯在今天(或我指定的日期,如2023-03-30
)。
我知道这在MongoDB中是可能的,但我不确定如何在查询代码中表达这一点。
顺便说一下,expiryDate
存储在这种格式(像字符串)2023-03-30
,但我仍然可以使用gte, lte, gt, lt, etc
。如果没有弄错的话,我的MongoDB版本是4.4。
我尝试使用$dateAdd(aggregate),但它不起作用,因为这需要5.0版本。
我还尝试了$add(aggregate)with date,但将天数/月计算为毫秒可能会遇到每月天数(28-31天)的问题。
是否有一个添加功能,我可以很容易地添加几个月前直接没有计算毫秒,并将与版本4.4?
更新
经过一些研究,我能够创建一个满足我需要的查询,但我知道这不是最好的或有效的查询,但这对我来说很有效。
db.getCollection('torjak_requests').aggregate(
[
{
$match: {
/* Add your filters here */
}
},
// Add temporary field to convert String date to ISO Date
{
$addFields: {
"expiryDate" : {
$dateFromString: {
dateString: "$expiryDateS"
}
}
}
},
// Add temporary fields for 1 month and 3 months before expiry date in ISO Date format
{
$addFields: {
"expiryDate1MonthBefore" : {
$dateFromParts: {
year: { $year: "$expiryDate" },
month: { $add: [{ $month: "$expiryDate" }, -1] },
day: { $dayOfMonth: "$expiryDate" },
hour: { $hour: "$expiryDate" },
minute: { $minute: "$expiryDate" },
second: { $second: "$expiryDate" },
millisecond: { $millisecond: "$expiryDate" }
}
},
"expiryDate3MonthsBefore" : {
$dateFromParts: {
year: { $year: "$expiryDate" },
month: { $add: [{ $month: "$expiryDate" }, -3] },
day: { $dayOfMonth: "$expiryDate" },
hour: { $hour: "$expiryDate" },
minute: { $minute: "$expiryDate" },
second: { $second: "$expiryDate" },
millisecond: { $millisecond: "$expiryDate" }
}
}
}
},
// Add fields for 1 month and 3 months before expiry in String format
{
$addFields: {
"expiryDate1MonthBeforeS" : {
$dateToString: { format: "%Y-%m-%d", date: "$expiryDate1MonthBefore" }
},
"expiryDate3MonthsBeforeS" : {
$dateToString: { format: "%Y-%m-%d", date: "$expiryDate3MonthsBefore" }
},
}
},
// Remove temporary added fields since I don't need these fields anymore
{
$projection: {
"expiryDate" : 0,
"expiryDate1MonthBefore" : 0,
"expiryDate3MonthsBefore" : 0
}
}
]
)
1条答案
按热度按时间mspsb9vt1#
最简单的,也可能是性能最好的方法是在客户端计算日期,这需要在每个查询中计算一次,而不是在每个文档中计算一次。
然后,查询就变成了字符串的简单范围比较。
使用您喜欢的日期库定义比较日期字符串:
则查询将于今天过期:
1个月前(但不是今天):
超过1个月至3个月前: