Как найти следующие N элементов из курсора с MongoDB, без _id и отсортированного курсора - PullRequest
3 голосов
/ 04 февраля 2020

Допустим, у меня есть документы из трех человек в MongoDB, вставленные в случайном порядке.

{
  "firstName": "Hulda",
  "lastName": "Lamb",
},
{
  "firstName": "Austin",
  "lastName": "Todd",
},
{
  "firstName": "John",
  "lastName": "Doe",
}

Моя цель - получить, скажем, следующего человека после Остина, когда список в алфавитном порядке , Поэтому я хотел бы получить человека с firstName = Hulda. Можно предположить, что я знаю Остина _id. Моей первой попыткой было положиться на тот факт, что _id является инкрементным, но это не сработает, потому что людей можно добавлять в базу данных в любом порядке. Поле _id Хульды имеет значение меньше, чем у Остина. Я не могу сделать что-то вроде {_id: {$gt: <Austin's _id here>}}; И мне также нужно ограничить количество возвращаемых элементов, так что N - это динамическое c значение.

Вот код, который у меня есть сейчас, но, как я уже говорил, Идентификационный трюк не работает.

let cursor: any = this.db.collection(collectionName).find({_id: {$gt: 
cursor = cursor.sort({firstName: 1});
cursor = cursor.limit(limit);

return cursor.toArray();

Некоторые пояснения:

  1. startId является действующим, существующим _id объекта
  2. limit является переменная, содержащая положительное целочисленное значение
  3. , сортировка и ограничение работают как положено, просто выбор следующих элементов неверен, поэтому {_id: {$gt: startId}}; портит выбор.

1 Ответ

5 голосов
/ 04 февраля 2020

Контекст каждой операции MongoDB Aggregation Framework ограничен одним документом. В SQL нет такого механизма, как оконные функции. Ваш единственный способ - использовать $group, чтобы получить массив, содержащий все ваши документы, а затем получить индекс Austin, чтобы можно было применить $ slice :

db.collection.aggregate([
    {
        $sort: { firstName: 1 }
    },
    {
        $group: {
            _id: null,
            docs: { $push: "$$ROOT" }
        }
    },
    {
        $project: {
            nextNPeople: {
                $slice: [ "$docs", { $add: [ { $indexOfArray: [ "$docs.firstName", "Austin" ] }, 1 ] }, 1 ]
            }
        }
    },
    { $unwind: "$nextNPeople" },
    {
        $replaceRoot: {
            newRoot: "$nextNPeople"
        }
    }
])

Пн go Детская площадка

В зависимости от размера ваших данных / производительности MongoDB, указанное выше решение может быть или не быть приемлемым - вы сами решаете, хотите ли вы развернуть такой код на производстве так как $group операция может быть довольно тяжелой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...