使用MongoDB和Nodejs插入和查询日期

50

我需要在mongodb和nodejs中通过日期找到一条记录。

我在一个爬取脚本中将日期添加到json对象中,如下所示:

jsonObj.last_updated = new Date();

该对象已插入到MongoDB中,我可以在下面看到它:

 "last_updated" : "2014-01-22T14:56:59.301Z"

然后在我的nodejs脚本中,我执行findOne():

 var jObj = JSON.parse(line.toString());

 collection.findOne(jObj,function(err, doc) {
   if (doc){
     console.log(doc._id);
   } else  {
     console.log('not found');
   }
 });

对象未找到。如果我从对象中删除last_updated字段,则可以找到它,因此问题肯定出在这里。

如果我按以下方式隔离该字段:

collection.findOne({last_updated: '2014-01-22T14:56:59.301Z'},function(err, doc) {
  if (doc){
    console.log(doc._id);
  } else  {
    console.log('not found');
  }
});

没有任何回应。我做错了什么吗?


1
new Date(Date.now()).toISOString() - r3wt
5个回答

82
您需要传递一个日期对象而不是日期字符串。
collection.findOne({last_updated: new Date('2014-01-22T14:56:59.301Z')},function(err, doc) {

MongoDB驱动程序将其转换为ISODate

{ 
   "_id" : ObjectId("52dfe0c469631792dba51770"), 
   "last_updated" : ISODate('2014-01-22T14:56:59.301Z') 
}

请检查以下问题:


2
结合 momentjs 的用法:Items.find({sellingState: "Active", endTime: {$lt: new Date(moment().subtract(1, 'day').toISOString())}}, {limit: 10}) - Quake1TF
1
现在使用new Date而不需要括号来存储。 - tim-phillips
不要在插入MongoDB数据库时使用new Date().toISOString()(而只需使用new Date()),因为MongoDB已经为您执行了转换,而使用 .toISOString() 将使数据库上的.find()操作或$gte操作失败。 - Yi Xiang Chong
在使用Node 12.18和mongo 3.4.1时,不带括号使用new Date会给我与带括号使用它相同的结果(即一个UTC ISODate)的文档。 - Toomy

14

澄清一下,需要知道的是:

  • 是的,您必须传递一个Javascript日期对象。
  • 是的,它必须是ISODate友好格式。
  • 是的,根据我的经验,您需要将日期转换为ISO格式以使其正常工作。
  • 是的,与日期打交道通常都是一个乏味的过程,Mongo也不例外。

这是一个可行的代码片段,我们在其中进行了一些日期操作,以确保Mongo能够正确处理它。在此示例中,我使用mongoose模块,并希望获得日期属性早于(即之前)myDate参数给定日期的结果行。

var inputDate = new Date(myDate.toISOString());
MyModel.find({
    'date': { $lte: inputDate }
})

3
myDate参数的样式是怎样的?它是字符串'Mon Feb 29 2016 21:04:59 GMT+0100 (CET)'吗? - Matko
我认为这是不正确的,并且犯了相同的错误,导致我的现有数据库出现错误。在插入MongoDB数据库时不要使用new Date().toISOString()(而只需使用new Date()),因为MongDB已经为您执行了转换,而使用.toISOString()将使数据库上的.find()操作或$gte操作失败。 - Yi Xiang Chong

7

我最近遇到了同样的问题,想要添加一些额外的信息。

您可以通过两种方式插入日期:

  1. 在nodejs服务器端创建(例如,在ExpressJS脚本中)

示例:插入一个新对象并打上时间戳

db.collection('mycollection').findOneAndUpdate({'name': req.body.name}, {
  // only "update" if it's an insert, meaning name is not found
  $setOnInsert: {
    'name': req.body.name,
    'date_added': new Date()
  }
}, { 
  upsert: true
}, (err, result) => {
  if(err) return res.send(err);
  res.send(result);
});
  1. 从JS客户端创建并通过REST API以JSON对象的形式通过POST请求发送到服务器端

示例:

// Send POST Request here
fetch('addDate', {
  method: 'post',
  headers: {'Content-Type': 'application/json'},
  body: JSON.stringify({
    'date_added':  new Date()
  })
})

对于1和2,您可以使用上面的答案中解释的new Date('2014-01-22T14:56:59.301Z')函数创建日期。区别在于,如果您像1中那样在服务器端使用MongoClient包进行操作,则会将其存储为MongoDB中的ISODate('2014-01-22T14:56:59.301Z')。如果您像2中那样在客户端进行操作,则以字符串形式存储:在MongoDB中为'2014-01-22T14:56:59.301Z'
要查询ISODate对象,您需要使用new Date('2014-01-22T14:56:59.301Z')ISODate('2014-01-22T14:56:59.301Z')。要查询字符串,只需使用该字符串:'2014-01-22T14:56:59.301Z' 以下是使用mongo shell的一些查询示例:
存储为字符串的日期:
db.mycollection.findOne({date_added {$gte:'2018-06-22T00:07:53.688Z'}})

这会返回:

这会返回

{
  "_id" : ObjectId("5b2c3dd90078ce3cd484ef21"),
  "name" : "alfons",
  "date_added" : "2018-06-22T00:07:53.688Z"
}

日期使用ISODate格式存储:

db.mycollection.findOne({date_added: {$lte: ISODate('2018-06-26T23:24:37.023Z')}})

或者使用"new Date"代替:

db.mycollection.findOne({date_added: {$lte: new Date('2018-06-26T23:24:37.023Z')}

这段代码返回以下结果:
{
  "_id" : ObjectId("5b2bb21e1954b104e61ff735"),
  "name" : "ceasar",
  "date_added" : ISODate("2018-06-21T14:11:41.323Z")
}

1
在模式中添加默认键,并将其值设置为 Date.now()。保留 HTML,不要解释。

如何在模式中添加默认键? - Scott Fleming
1
publishedAt:{ type:Date, default:Date.now() } - user9032626

-1
如果您使用时间戳数据进行查询。例如:"createdAt":"2021-07-12T16:06:34.949Z"
const start  = req.params.id; //2021-07-12
const data = await Model.find({
            "createdAt": {
              '$gte': `${start}T00:00:00.000Z`,
              '$lt': `${start}T23:59:59.999Z`
            }
          });
console.log(data);

它将显示特定日期的数据,即在这种情况下是“2021-07-12”


在 ISO 字符串中硬编码时间并不是 OP 的问题的答案。 - thelearner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接