猫鼬:按日期运行预定作业查询

时间:2017-04-07 04:25:43

标签: node.js mongodb mongoose

我想为医院的病人创建预定的工作。每个月都会通过reg_date通知患者。

我在预定的工作中使用new Date().getDate()在早上8点运行,向我的病人发送短信。同时,我一直在使用字符串格式日期来保存我的mongoDB中的reg_date。以下是我的mongoDB文档的片段:

{
    customer: "John",
    reg_date: "2017-02-17T16:39:26.969Z"
}

我一直在寻找解决方案,但事实证明没有,所以我决定发布自己。这是我想要做的:

customer.find({"reg_date.getDate()" : new Date(2017, 03, 17).getDate()})
    .then(function(data) {
      for (var key in data.length) {
          sendTheSMS(key[data]);
      };
    });

例如:我正在做的是"我希望让每位患者在每月的第17天注册并向他们发送短信"。

任何帮助将不胜感激。 :d

4 个答案:

答案 0 :(得分:1)

对于这种类型的位复杂查询,您需要使用聚合方法而不是常规的查找方法。

$project这将有助于您投射字段,我们正在创建一个新的临时字段day,其日期仅为reg_date。然后我们使用新的字段日查询,我们得到结果。

此临时字段day永远不会添加到您的架构或模型中,就像我们在SQL中创建的临时视图一样。

这里我只预测了客户和日期,但请在结果中预测所需的所有字段。

function getCustomerList(day, callback){
    customer.aggregate([
      {
         $project:{
            "customer": "$customer",   //repeat the same for all field you want in result
            "reg_date": "$reg_date",
            "day":{$dayOfMonth:"$reg_date"}  //put day of month in 'day' 
         }
       },
      {
        $match:{
          "day": day  //now match the day with the incoming day value
      }
     },
   ], function(err, result){
        callback(err, result);            
   })
}

getCustomerList(17, function(err, result){   // call the function like this with date you want
   // Process the err & result here
}); 

结果将是这样的

[{
 "_id" : ObjectId("571f2da8ca97eb10163e6e17"),
 "customer" : "John",
 "reg_date" : ISODate("2016-04-17T08:58:16.414Z"),
 "day" : 17
},
{
 "_id" : ObjectId("571f2da8ca97eb10163e6e17"),
 "customer" : "Prasanth",
 "reg_date" : ISODate("2016-04-17T08:58:16.414Z"),
 "day" : 17
}]

忽略流程中投射的day字段...

答案 1 :(得分:1)

reg_date字符串中,您无法查询每月的某一天,因为它仅适用于ISODate。我建议您首先使用脚本在所有文档中转换reg_date中的字符串。

然后以下查询应该起作用

customer.aggregate([
{
    $project:{
            "document": "$$ROOT",   //to get the whole document
            "day":{$dayOfMonth:"$date"}  //put day of month in 'day' 
           }
    },
{
    $match:{
        "day": 17  //match 17
        }
    },

], function(data) {
  for (var key in data.length) {
      sendTheSMS(key[data]);
  };
})

答案 2 :(得分:0)

使用大于和小于

var previousDate =new Date(2017, 1, 16);   //month starts with 0
var nextDate=new Date(2017, 1, 18);

customer.find({reg_date : { $gt:previousDate,$lt:nextDate}})
.then(function(data) {
  for (var key in data.length) {
    sendTheSMS(key[data]);
  };
});

答案 3 :(得分:0)

由于reg_date存储为字符串,而不是日期/ ISODate,因此您可以限制使用哪种查询(因此我同意其他一个答案中的注释)您应该考虑将它们转换为正确的ISODate。)

考虑到您要查询具有特定日期的条目的日期字符串,您可以使用regular expression查询:

customer.find({ reg_date : /-17T/ })

或者,动态地:

let today = new Date();
let dom   = ('00' + today.getDate()).slice(-2); // zero-pad day of month
let re    = new RegExp('-' + dom + 'T');

customer.find({ reg_date : re })

您还应该阅读有关速度优化的this,但仍然,正则表达式查询速度非常快。