Mongodb подсчитывает документы за последние X недель - не последние XX дней - PullRequest
0 голосов
/ 07 мая 2020

хотя здесь есть аналогичные вопросы, как найти / подсчитать документы в конкретном диапазоне c недель, мне не удалось выяснить, как сопоставить / подсчитать документы за последние X недель. Рассмотрим этот запрос:

db.getCollection('post').aggregate([

   {
        $match: {
            createdDate: {'$gte': new Date(new Date() - 7 * 60 * 60 * 24 * 1000)},
        }
    },
    {
        $group: {
            _id: {$week: '$createdDate'},
            count: {$sum: 1}
        }
    }
])

Этот запрос подсчитывает документы за последние 7 дней и группирует счетчик по номеру недели, но результат фактически содержит два поля: количество документов за текущую неделю и количество документов с прошлой недели, начиная с дня, который является текущим днем ​​- 7 дней.

Пример - запрос начиная со среды:

  • Последние 7 дней предыдущие неделя: [чт, пт, сб, вс] | текущая неделя: [пн, вт, ср]
  • на прошлой неделе на предыдущей неделе: [пн, вт, ср, чт, пт, сб, вс] | текущая неделя: []

Запрос должен возвращать правильный результат, независимо от того, был ли он запущен в первый день недели или в последний день недели. Также необходимо учитывать изменение года - последняя неделя декабря имеет номер 52, первая неделя января - номер 1 недели.

Другие потенциальные проблемы могут возникнуть из-за недель без каких-либо связанных документов. Вы просто не можете сгруппировать документы за последние 21 день по номеру недели и использовать $sort и $limit, потому что недели без какого-либо связанного документа не появятся в группировке.

Ответы [ 2 ]

0 голосов
/ 11 мая 2020

Я потратил много времени, пытаясь найти собственное решение, основанное на операторе $week, и решил опубликовать его здесь, , но в конце концов я понял, что подход, предложенный harshit kohli лучше. Я объясню позже. После дальнейшего расследования я обратил внимание на то, что в первом ответе есть несколько серьезных ошибок aws, вызванных неделями без рассмотрения каких-либо связанных документов.

ОБНОВЛЕНИЕ:

Наконец-то я нашел решение, основанное на номерах недель, которое также должно давать правильные результаты, даже если запрос распространяется на изменение года. Ключ состоит в том, чтобы вычесть 52 (годовой номер недели)

db.getCollection('post').aggregate([
{
    {
       $match: { // match posts at least 2 Weeks + 6 days old
          createdDate: {'$gte':new Date(new Date().setDate(new Date().getDate() - 3 * 7 - 1))},
       }
    },
    {
       $addFields: {
          createdInWeek: { 
             $cond: {
                 if: {
                     $eq: [
                        { $year: "$createdDate"},
                        { $year: new Date()}
                     ]
                 }, then: {
                     $week: "$createdDate"
                 }, else: {
                     $subtract: [ { $week: "$createdDate"}, 52]
                 }
              }
          },
          currentWeek: { $week: new Date() },
      }
  },
  {
      $match: {
          $expr: {
              $and: [
                  {$lte: ["$createdInWeek", { $subtract: ["$currentWeek", 1] } ]},
                  {$gte: ["$createdInWeek", { $subtract: ["$currentWeek", 2] } ]},
              ]
          }
      }    
  },
  {
      $group: {
          _id: {$week: '$createdDate'},
          count: {
              $sum: 1
          }
      }
  },
])

Таким образом, все еще могут быть проблемы с годами, содержащими 53 недели, ссылка здесь

ПРЕДЫДУЩИЙ:

db.getCollection('post').aggregate([
{   // optional, can pre-sort your collection, so you don't add fields to every document in a huge collection
    $match: {
        createdDate: {'$gte':new Date(new Date().setDate(new Date().getDate() - 2 * 7 + 1))},
    }
},
{
    $addFields: {
        createdInWeek: { $week: '$createdDate' },
        currentWeek: { $week: new Date() },
    }
},
{
    $match: { // use of $expr. necessary since MongoDb 3.6 see https://stackoverflow.com/a/58567621/1991697
        $expr: {
           $and: [
              {$lte: ["$createdInWeek", { $subtract: ["$currentWeek", 1] } ]},
              {$gte: ["$createdInWeek", { $subtract: ["$currentWeek", 2] } ]},
           ]
        }
    }               
},
{
   $group: {
       _id: {$week: '$createdDate'},
       count: {
          $sum: 1
       }
    }
},    
])

Этот подход позволяет Mon go вычислять номера недель для текущей недели и createdDate для каждого документа в вашей коллекции, и вы можете выполнить простую сортировку файлов, используя дополнительные $match оператор. Это также позволит вам легче установить недельный диапазон.

НО

Это, вероятно, не удастся, если ваш недельный диапазон будет разделен на перерыв в году. (Первая неделя января - неделя 0, последняя неделя декабря - неделя 52)

0 голосов
/ 08 мая 2020

попробуйте добавить еще два этапа, сначала отсортируйте их на основе group _id, т.е. номера недели, затем ограничьте результат до 1

 db.getCollection('post').aggregate([

       {
            $match: {
                createdDate: {'$gte': new Date(new Date() - 15 * 60 * 60 * 24 * 1000)},
            }
        },
        {
            $group: {
                _id: {$week: '$createdDate'},
                count: {$sum: 1}
            }
        },
       {
         $sort:{
        _id:-1  
        }
       },
      {
       $skip:1
       },
       {
        $limit:1
       }
    ])
...