【问题标题】:Mongoose: Running Scheduled Job Query by DateMongoose:按日期运行计划作业查询
【发布时间】:2023-03-09 11:48:02
【问题描述】:

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

我在早上 8 点运行的预定作业中使用 new Date().getDate() 向我的患者发送 SMS。同时,我一直在使用字符串格式日期将reg_date 保存在我的 mongoDB 中。这是我的 mongoDB 文档的 sn-ps:

{
    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

【问题讨论】:

    标签: node.js mongodb mongoose


    【解决方案1】:

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

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

    这个临时字段 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 字段...

    【讨论】:

    • 感谢您的回复。但是,如果我输入日期 17,尽管有任何月份或年份,我仍然希望 John 再次出现。我不能用那个查询得到一个吗? :)
    • 安装的是什么版本的mongodb?
    • MongoDB 外壳版本:3.2.11
    • 答案对你有帮助吗?
    • 谢谢你的详细解释,它现在正在工作。我先花时间查看了aggregation$project 是什么东西,所以我下次可以使用它们。干杯芽!
    【解决方案2】:

    使用字符串中的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]);
      };
    })
    

    【讨论】:

    • 嗨,Talha,你的回答对我来说很有希望。我还是 mongoDB 和 mongoose ODM 的新手。您能否详细说明$project 部分?干杯。
    • 在聚合管道中使用。官方定义很有帮助:“project 将带有请求字段的文档传递到管道中的下一个阶段。”
    【解决方案3】:

    使用大于和小于

    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]);
      };
    });
    

    【讨论】:

    • 感谢您的回复。但是,如果我输入日期 17,我希望 John 再次出现,尽管有任何月份或年份。我不能用那个查询得到一个吗? :)
    【解决方案4】:

    由于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 关于速度优化的内容,但是,正则表达式查询仍然不是很快。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-09
      • 1970-01-01
      • 2010-09-12
      相关资源
      最近更新 更多