Создание таблицы лидеров с привязкой ко времени в Node.JS и MongoDB

У нас есть документ для каждого пользователя. Мы награждаем их «апельсинами» (внутриигровыми очками) за выполнение активностей.

Мы сохраняем заданные точки следующим образом:

У нас есть свое эпохальное время вместе с заработанными апельсинами. В настоящее время у нас есть общая цель totalOranges для создания постоянной таблицы лидеров.

Однако мы изо всех сил пытаемся определить, как составить таблицу лидеров за 24 часа и последние 7 дней. Мы можем рассчитать для каждого пользователя, но количество чтений будет безумным (более 10 тысяч пользователей). Есть ли более разумный способ сделать это?

🤔 А знаете ли вы, что...
Node.js имеет встроенные инструменты для отладки, включая инструменты для анализа кода и профилирования.


2
50
1

Ответ:

Решено

Чтобы выполнить вычисления над объектом на основе динамических ключей, проще всего преобразовать объект в формат массива с помощью $objectToArray, а затем обработать массив.

шаги, которые я использовал

  1. Преобразуйте поле объекта в массив и $filter массив, чтобы получить массив элементов, временная метка которых находится в пределах последних 7 (или n) дней. Теперь это входной массив для $reduce
  2. $reduce можно использовать для суммирования массива. сохраните сумму в отдельном поле
  3. сортировать по новому полю
db.collection.aggregate([
  {
    $addFields: {
      inbetweenTimePeriod: {
        $reduce: {
          input: {
            $filter: {
              input: { $objectToArray: "$sectional" },
              as: "item",
              cond: {
                $gte: [
                  { $toLong: "$$item.k" },
                  {
                    $divide: [ { $subtract: [ { $toLong: "$$NOW" }, 604800000 ] }, 1000 ]
                    //(epoch now in ms - 7days in ms) in seconds
                  }
                ]
              }
            }
          },
          initialValue: 0,
          in: { $add: [ "$$value", "$$this.v" ] }
        }
      }
    }
  },
  { $sort: { inbetweenTimePeriod: -1 } }
])

детская площадка