在特定日期查询 MongoDB/Mongoose?

是否可以查询特定的日期?

我在 mongo Cookbook 中发现,我们可以查询一个日期范围 就像这样:

db.posts.find({"created_on": {"$gte": start, "$lt": end}})

但是有没有可能确定一个特定的日期呢? 这样行不通:

db.posts.find({"created_on": new Date(2012, 7, 14) })
289217 次浏览

如果您保存在 DB 中的日期没有时间(只有年、月、日) ,那么应该可以工作。

您保存的日期有可能是 new Date(),其中包括时间成分。要查询这些时间,您需要创建一个包含一天中所有时刻的日期范围。

db.posts.find({ //query today up to tonight
created_on: {
$gte: new Date(2012, 7, 14),
$lt: new Date(2012, 7, 15)
}
})

你有没有试过:

db.posts.find({"created_on": {"$gte": new Date(2012, 7, 14), "$lt": new Date(2012, 7, 15)}})

您将遇到的问题是,日期在 Mongo 中以时间戳的形式存储。所以,为了匹配一个日期,你要求它匹配一个时间戳。就你的情况而言,我认为你是在试图匹配一天(即。在指定日期由零时至二十三时五十九分)。如果您的日期存储没有时间,那么您应该没有问题。否则,请尝试将您的日期指定为同一天的一个时间范围(即。Start = 00:00,end = 23:59)如果 gte 不工作。

类似的问题

我们遇到了一个与数据库中的重复数据有关的问题,日期字段有多个值,其中应该有1。我想我应该加上我们解决问题的方式,以供参考。

我们有一个名为“ data”的集合,其中有一个数字“ value”字段和一个 date“ date”字段。我们有一个过程,我们认为是幂等的,但最终在第二次运行时每天增加2 x 值:

{ "_id" : "1", "type":"x", "value":1.23, date : ISODate("2013-05-21T08:00:00Z")}
{ "_id" : "2", "type":"x", "value":1.23, date : ISODate("2013-05-21T17:00:00Z")}

我们只需要2条记录中的1条,因此必须使用 javascript 来清理数据库。我们最初的方法是在结果中进行迭代,删除上午6点到11点之间的任何字段(所有重复的字段都在上午) ,但是在实现过程中做了一些改变。下面是用来修复它的脚本:

var data = db.data.find({"type" : "x"})
var found = [];
while (data.hasNext()){
var datum = data.next();
var rdate = datum.date;
// instead of the next set of conditions, we could have just used rdate.getHour() and checked if it was in the morning, but this approach was slightly better...
if (typeof found[rdate.getDate()+"-"+rdate.getMonth() + "-" + rdate.getFullYear()] !== "undefined") {
if (datum.value != found[rdate.getDate()+"-"+rdate.getMonth() + "-" + rdate.getFullYear()]) {
print("DISCREPENCY!!!: " + datum._id + " for date " + datum.date);
}
else {
print("Removing " + datum._id);
db.data.remove({ "_id": datum._id});
}
}
else {
found[rdate.getDate()+"-"+rdate.getMonth() + "-" + rdate.getFullYear()] = datum.value;
}
}

然后用 mongo thedatabase fixer_script.js进行测试

是的,Date 对象完成日期和时间,所以将其与单独的日期值进行比较不起作用。

您可以简单地使用 < strong > $where 操作符来表达更复杂的条件,包括 Javascript 布尔表达式:)

db.posts.find({ '$where': 'this.created_on.toJSON().slice(0, 10) == "2012-07-14"' })

created_on是日期时间字段,2012-07-14是指定的日期。

日期应该正好是 YYYY-MM-DD格式。

注意: 尽量少用 $where,它对性能有影响。

... 5年以后,我强烈建议使用 约会代替

import endOfDayfrom 'date-fns/endOfDay'
import startOfDay from 'date-fns/startOfDay'


MyModel.find({
createdAt: {
$gte: startOfDay(new Date()),
$lte: endOfDay(new Date())
}
})

对于我们这些使用 等一下的人来说

const moment = require('moment')


const today = moment().startOf('day')


MyModel.find({
createdAt: {
$gte: today.toDate(),
$lte: moment(today).endOf('day').toDate()
}
})

重要提示: 所有的时刻都是可变的

调用 moment(today)通过隐式克隆 today解决了这个问题。

你可以使用下面的 API 方法从特定的一天得到结果:

# [HTTP GET]
getMeals: (req, res) ->
options = {}
# eg. api/v1/meals?date=Tue+Jan+13+2015+00%3A00%3A00+GMT%2B0100+(CET)
if req.query.date?
date = new Date req.query.date
date.setHours 0, 0, 0, 0
endDate = new Date date
endDate.setHours 23, 59, 59, 59
options.date =
$lt: endDate
$gte: date


Meal.find options, (err, meals) ->
if err or not meals
handleError err, meals, res
else
res.json createJSON meals, null, 'meals'

似乎没有一个答案对我有用。尽管有人提到了一个小提示,我还是设法使它与下面的代码一起工作。

let endDate = startingDate
endDate = endDate + 'T23:59:59';


Model.find({dateCreated: {$gte: startingDate, $lte: endDate}})

startingDate将是您要查询的具体日期。

我更喜欢这个解决方案,以避免安装 moment,只是通过 startingDate喜欢在邮递员的 "2021-04-01"

下面给出了一个非常简单的解决方案

const start = new Date(2020-04-01);
start.setHours(0, 0, 0, 0);
const end = new Date(2021-04-01);
end.setHours(23, 59, 59, 999);
queryFilter.created_at={
$gte:start,
$lte:end
}
YourModel.find(queryFilter)

因此,上面的代码只是查找从给定开始日期到给定结束日期的记录。

我用这种方法做,效果很好

  public async getDatabaseorderbyDate(req: Request, res: Response) {
const { dateQuery }: any = req.query
const date = new Date(dateQuery)
console.log(date)
const today = date.toLocaleDateString(`fr-CA`).split('/').join('-')
console.log(today)
const creationDate = {
"creationDate": {
'$gte': `${today}T00:00:00.000Z`,
'$lt': `${today}T23:59:59.999Z`
}
};


`
``

我遇到的问题是在后端过滤日期,当设置日期为0小时,0分钟,0秒,0毫秒在节点服务器它在 ISO 时间,所以当前日期0小时,0分钟,0秒,0毫秒的客户端可能会有所不同,也就是说,结果可能给一天之后或之前,由于转换 ISO 时间到本地时区

我通过将本地时间从客户机发送到服务器来修复这些问题

 // If client is from Asia/Kathmandu timezone it will zero time in that zone.
// Note ISODate time with zero time is not equal to above mention
const timeFromClient = new Date(new Date().setHours(0,0,0,0)).getTime()

并使用此时间通过使用此查询过滤文档

const getDateQuery = (filterBy, time) => {
const today = new Date(time);
const tomorrow = new Date(today.getDate() + 1);


switch(filterBy) {
case 'past':
return {
$exists: true,
$lt: today,
};
case 'present':
return {
$exists: true,
$gte: today,
$lt: tomorrow
};
case 'future':
return {
$exists: true,
$gte: tomorrow
};
default:
return {
$exists: true
};
};
};
const users = await UserModel.find({
expiryDate: getDateQuery('past', timeFromClient)
})

如果我们有 timezoneId,比如 Asia/Kathmandu,那么可以用另一种使用聚合的方法来完成

const getDateQuery = (filterBy) => {
const today = new Date();
const tomorrow = new Date(today.getDate() + 1);


switch(filterBy) {
case 'past':
return {
$exists: true,
$lt: today,
};
case 'present':
return {
$exists: true,
$gte: today,
$lt: tomorrow
};
case 'future':
return {
$exists: true,
$gte: tomorrow
};
default:
return {
$exists: true
};
};
};
await UserModel.aggregate([
{
$addFields: {
expiryDateClientDate: {
$dateToParts: {
date: '$expiryDate',
timezone: 'Asia/Kathmandu'
}
}
},
},
{
$addFields: {
expiryDateClientDate: {
$dateFromParts: {
year: '$expiryDateClientDate.year',
month: '$expiryDateClientDate.month',
day: '$expiryDateClientDate.day'
}
}
},
},
{
$match: {
expiryDateClientDate: getDateQuery('past')
}
}
])