首页 > 解决方案 > 查找日期在从现在起一分钟内的条目,但与日期无关

问题描述

我进行了查询,查找日期字段在下一分钟内的所有条目:

import { addMinutes, format } from 'date-fns'
date: {
    $gte: new Date(),
    $lt: (addMinutes(new Date(), 1))
}

但是,这仅适用于日期与今天相同的情况。现在,如果我希望无论日期字段中的哪一天都可以正常工作,我该怎么办?

用例如下:创建文档时,日期字段设置为 Date.now()。如果没有年、月或日,我想获取从现在起在一分钟内创建的所有文档。这也应该包含几个小时和几天,所以如果现在是 23:59:30,我想找到在任何一天 23:59:30 或更晚或 00:00:30 之前创建的所有文档。

基本上我只想从我的日期字段中提取小时分钟和秒,并使用它们。但我找不到办法做到这一点。

这是一个示例文档:

    "_id": "5f2447d259aaf231d8dc1d3b",
    "date": "2020-08-07T12:22:00.000Z",
    "enabled": true,

标签: mongodb

解决方案


这有效并解释了午夜的重叠。它需要一些来自 js 的变量,所以我不能做游乐场。它通过将任何给定时间转换为一天中的分钟来工作。00:00:30 = 0.5 和 23:59:30 = 1439.5。然后 $match 可以根据当前时间使用 $gt $lt 运算符的组合。

根据集合的大小,您可能希望将分钟值添加到架构中,然后在保存文档时计算它。然后可以删除 $addFields 阶段,您可以使用索引。现在这会扫描所有文档。

编辑:我刚刚重新阅读了你的问题,并看到你在当前时间之后唯一寻找的。编辑为仅在下一分钟内包含文档

// Set the range 'fromNow' to query docs
const range = 1; // minutes

const now = new Date(); // Insert a date to test overlaps '2020-03-12T23:59:50.000+00:00'

// Get the current minute of the day in a usualable format ie: 1200.42
const currentMinute = 
  now.getUTCHours()*60 + now.getUTCMinutes() + now.getUTCSeconds()/60;

const result = await Item.aggregate([
  // Convert the date of each doc to the same 'currentMinute' format ie: 1200.42
  {$addFields: {
    time: {$add:[
      {$multiply: [{$hour: '$date'}, 60]},
      {$minute: '$date'},
      {$divide: [{$second: '$date'}, 60]}
    ]},
  }},

  {$match: {
    $expr: {$or: [
      // Match any docs that time are within the range
      {$and: [
        // The docs date is after now
        {$gte: ['$time', currentMinute]},
        {$lte: ['$time', currentMinute + range]}
      ]},

      // Now account for days end
      // If its 11:59:31 then include docs before 00:00:31
      {$cond: [
        // If current minute + range is greater than day end (1440)
        {$gt: [currentMinute + range, 1440]},
        // Then include docs that's time is less than currentMin + range - 1440
        {$lte: ['$time', currentMinute + range - 1440]},
        // Else null to ignore this $match stage
        null
      ]},
    ]}
  }}
]);

console.log('result', result);

推荐阅读