Является ли шаблон сегмента в MongoDb лучшим способом обработки больших неограниченных массивов? - PullRequest
0 голосов
/ 28 апреля 2020

Я внедряю социальные функции в приложение стека MERN (отслеживание / отмена подписки) и пытаюсь найти хорошее решение MongoDB для избежания проблем с потенциально большими неограниченными массивами подписчиков. В частности, я надеюсь избежать:

  • MongoDB, чтобы перемещать большой массив подписчиков на диск и перестраивать индексы по мере его увеличения
  • , превышая предел 16 МБс по Бсону, если пользователь когда-либо достигнет очень большое количество подписчиков (> 1 миллион)
  • низкая производительность при запросе / возврате подписчиков для отображения через нумерацию страниц или при расчете / отображении количества подписчиков

Из всего, что есть в Iv'e исследовано, кажется, что использование подхода с использованием шаблона ведра является лучшим решением ... две хорошие статьи, которые я нашел по этому вопросу: https://www.mongodb.com/blog/post/paging-with-the-bucket-pattern--part-1 https://www.mongodb.com/blog/post/paging-with-the-bucket-pattern--part-2

I Мы начали подходить к этому следующим образом ... Модель подписчика:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const FollowerSchema = new Schema({
  user: {
    type: Schema.Types.ObjectId,
    ref: 'user',
  },
  // creating an array of followers
  followers: [
    {
      user: {
        type: Schema.Types.ObjectId,
        ref: 'user',
      },
      datefol: {
        type: Date,
        default: Date.now,
      },
    },
  ],
  count: {
    type: Number,
  },
  createdate: {
    type: Date,
    default: Date.now,
    required: true,
  },
});

module.exports = Follower = mongoose.model('follower', FollowerSchema);

Вставить в Node.js API, чтобы добавить подписчика в корзину массива (каждая корзина будет содержать 100 подписчиков):

const follow = await Follower.updateOne(
        { user: req.params.id, count: { $lt: 100 } },
        {
          $push: {
            followers: {
              user: req.user.id,
              datefol: Date.now(),
            },
          },
          $inc: { count: 1 },
          $setOnInsert: { user: req.params.id, createdate: Date.now() },
        },
        { upsert: true }
      );

Обычно каждый раз, когда добавляется подписчик, он добавляет их к первому найденному сегменту, который содержит менее 100 подписчиков (отслеженных по количеству).

Является ли это лучшим подходом для обработки потенциальных ли большие массивы? Я обеспокоен тем, что:

  • , если кто-то отменит подписку пользователя и приложение запускает $ pull, чтобы удалить подписчика из массива в одном из сегментов ... тогда несколько блоков могут содержать менее 100 подписчиков. Новые подписчики больше не будут добавляться в самое последнее ведро, поэтому позже, при запросе и попытке вернуть подписчиков, основываясь на самых последних созданных корзинах ... некоторые из новейших подписчиков могут быть в более старом корзине и возвращаться неправильно. В вышеприведенных статьях упоминаются некоторые выразительные инструкции по обновлению, представленные в MongoDb 4.2, которые решают эту проблему, но мне не совсем понятно, как.
  • , если я исправлю это, возвращая все корзины последователей для пользователя и сортируя по дате следования ... кажется, что это может стать очень медленным, если у кого-то будет тонна подписчиков
  • , если я хочу иметь возможность разбивать на страницы и возвращать 100 подписчиков на страницу, начиная с последней, как это будет работать с таким подходом ? Должен ли я добавить запись номера страницы в модель и каким-то образом увеличивать ее при каждом создании корзины (первая корзина содержит номер страницы 1, следующая страница 2 и т. Д. c), а затем на переднем конце, если пользователь переходит на страницу подписчика 500 выполняется запрос, чтобы вытащить корзину 500?
...