MongoDb — возвращает массу N элементов с конца вложенного массива, зацикливаясь назад при каждом вызове (разбивка на страницы)

У меня есть коллекция категорий, и каждая категория имеет свой массив _id из другой коллекции. Моя цель - создать бесконечную прокрутку, предоставляя N записей каждый раз, но с конца (последняя запись всегда самая последняя).

Категория

{ 
    "_id" : ObjectId("625167ce3859b8465ccf69dc"), 
    "name" : {
        "en" : "Category #1"
    }, 
    "tracks" : [
        ObjectId("627f8475c229513838eed070"), 
        ObjectId("627f84b4c229513838eed074"), 
        ObjectId("6280ef548b97521c1f462266"), 
        ObjectId("6280ef68d147e83534f4ca03"), 
        ObjectId("6280ef6ad147e83534f4ca07"), 
        ObjectId("6280ef6bd147e83534f4ca0b"),
        // and so on..
    ]
}

Код:

categories
    .aggregate([
      {
        $match: {
          _id: ObjectId(categoryId),
        },
      },
      {
        $project: {
          tracks: {
            $slice: ["$tracks", -N],
          },
        },
      },
      {
        $lookup: {
          from: "tracks",
          as: "tracks",
          localField: "tracks",
          foreignField: "_id",
          pipeline: [{ $sort: { uploadedDate: -1 } }],
        },
      },
    ])

Итак, в основном я нарезаю массив, чтобы получить последние N элементов, а затем просматриваю их в коллекции tracks. Но я хочу получить N записей с конца между определенным диапазоном. Например, если у меня есть 100 записей, поэтому я задаю номер итерации 0 и объемный размер: 25, будут возвращены последние 25 элементов (индекс 75-99). На итерации 1 будут возвращены следующие (в обратном направлении) 25 элементов (индекс 50-74) и так далее...

@nimrodserok можешь показать пример? если я добавлю skip, это применит категории, но не треки. Также я хочу, чтобы это было эффективно, чтобы сделать это до поиска, чтобы он работал быстрее.

daniel93 15.05.2022 15:40

На самом деле вы можете использовать $slice с позиции: видеть это

nimrod serok 15.05.2022 15:58

@nimrodserok это то, что я пробовал, но я не могу использовать отрицательное число, если добавлю position. дело в том, что мне нужно N записей с конца (последний элемент всегда самый последний), поэтому мне нужно 25 записей из последнего индекса - 25 и т. д. Я могу нарезать до -N, но это всегда даст 25, 50 , 75 последних записей (придется загружать одни и те же элементы + 25 новых), а не 25 записей каждый раз между определенным диапазоном

daniel93 15.05.2022 16:07

Я не понимаю, что ты говоришь. Если у вас есть список из 100 документов, вы можете получить последний диапазон X ИЛИ (от индекса a до индекса c), по логике вещей, таких вещей нет, оба из них... Вы хотите, чтобы запрос дал вам один из эти параметры в соответствии с его вводом?

nimrod serok 15.05.2022 16:45

@nimrodserok скажем, у меня есть 10 тысяч документов, я хочу каждый раз получать 25 документов. документ 10K самый последний, поэтому мне нужно получить документы с конца.. 10 000 до 9 975, а затем 9 975 до 9 950 и так далее. дело в том, что мне нужно получить N элементов между определенным диапазоном, но с конца коллекции, если есть способ сделать это, надеюсь, это понятно.

daniel93 15.05.2022 16:59
Использование JavaScript и MongoDB
Использование JavaScript и MongoDB
Сегодня я собираюсь вкратце рассказать о прототипах в JavaScript, а также представить и объяснить вам работу с базой данных MongoDB.
0
5
34
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете так что-то вроде:

Обновлено: для поддержки крайних случаев:

db.collection.aggregate([
  {
    $match: {_id: ObjectId("625167ce3859b8465ccf69dc")}
  },
  {
    $addFields: {
      avilableCount: {$max: [
        {$subtract: [{$size: "$tracks" }, bulkSize * iterations]},  
      0]}
    }
  },
   {
    $project: {
      tracks: {
        $cond: [{$eq: ["$avilableCount",  0]},
          [],
          {$slice: ["$tracks", {
                $max: [
                  {$subtract: [{$size: "$tracks"}, bulkSize * (iterations + 1)]}, 0]},
              {$min: [bulkSize , "$avilableCount"]}
            ]
          }
        ]
      }
    }
  }
])

Пример детской площадки

Это вернет вам большую часть дорожек с размером bulkSize, начиная с конца списка для первой итерации и идя назад по итерациям. Итак, если у вас есть 100 дорожек с индексом 0-99 и bulkSize равно 25, вы получите дорожки 75-99 для первой итерации, 50-74 для 2-й итерации и 25-49 для 3-й... avilableCount позволяет нам взглянуть на крайние случаи: В крайнем случае, когда доступна только часть объема, он вернет эту часть, а если он недоступен, он вернет [].

Это то, что я хотел, но в случае, если у меня 85 страниц, bulkSize равен 25, а итерация - 3, он должен возвращать индексы 0-9, а не 71-85. А также есть ли способ использовать условия? если bulkSize * (итерации + 1) > track.length, чтобы не возвращать элементы по умолчанию? (Мне нужно знать, когда это закончится, поэтому я перестану прокручивать пользователя)

daniel93 15.05.2022 18:14

Обновил вопрос в соответствии с комментарием

nimrod serok 15.05.2022 19:38

Я думаю, это именно то, чего я пытался добиться, работая так, как ожидалось. спасибо, ачи, я ценю!

daniel93 15.05.2022 22:52

Другие вопросы по теме