Агрегация MongoDB: как получить индекс документа в коллекции в зависимости от сортировки по свойству документа

Предположим, у меня есть коллекция с миллионами документов. Ниже приведен пример того, как выглядят документы

[
    { _id:"1a1", points:[2,3,5,6] },
    { _id:"1a2", points:[2,6] },
    { _id:"1a3", points:[3,5,6] },
    { _id:"1b1", points:[1,5,6] },
    { _id:"1c1", points:[5,6] },
    // ... more documents
]

Я хочу запросить документ с помощью _id и вернуть документ, который выглядит следующим образом:

{
    _id:"1a1",
    totalPoints: 16,
    rank: 29
}

Я знаю, что могу запросить весь документ, отсортировать по убыванию, затем получить индекс нужного документа с помощью _id и добавить его, чтобы получить его рейтинг. Но у меня есть опасения по поводу этого метода. Если документы исчисляются миллионами, не будет ли это «перебором». Запрашивать всю коллекцию только для того, чтобы получить один документ? Есть ли способ добиться того, чего я хочу достичь, не запрашивая всю коллекцию? Или вся коллекция должна быть задействована из-за рейтинга?

Я не могу сохранить их рейтинг, потому что очки продолжают меняться. Фактический код более сложен, но вывод заключается в том, что я не могу сохранить их ранжированные.

Общее количество баллов — это сумма баллов в массиве баллов. Ранг рассчитывается путем сортировки всех документов в порядке убывания. Первый документ становится рангом 1 и так далее.

Я смотрю на потоки изменений. Похоже, они могут решить мою проблему.

YulePale 14.12.2020 04:52

как именно рассчитывается ранг? это позиция документа после сортировки по totalPoints?

Dĵ ΝιΓΞΗΛψΚ 14.12.2020 06:11

@ĐĵΝιΓΞΗΛψΚ да. Общее количество баллов — это сумма баллов в массиве баллов. Ранг рассчитывается путем сортировки всех документов в порядке убывания. Первый документ становится рангом 1 и так далее.

YulePale 14.12.2020 06:18

получите их в порядке убывания и используйте .forEach, добавив один, и если идентификатор является вашим идентификатором, верните его.

Minsky 14.12.2020 06:42

моя проблема не в использовании $group. Моя проблема в том, что я хочу отсортировать все документы в коллекции и получить индекс данного документа в этой коллекции. Должен ли я запрашивать все документы, выполнять сортировку и получать индекс, или есть ярлык, который не включает запрос всех документов только для того, чтобы получить один?

YulePale 14.12.2020 06:46
Использование JavaScript и MongoDB
Использование JavaScript и MongoDB
Сегодня я собираюсь вкратце рассказать о прототипах в JavaScript, а также представить и объяснить вам работу с базой данных MongoDB.
1
5
667
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

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

db.collection.aggregate(
[
    {
        $group: {
            _id: null,
            docs: {
                $push: { _id: '$_id', totalPoints: { $sum: '$points' } }
            }
        }
    },
    {
        $unwind: '$docs'
    },
    {
        $replaceWith: '$docs'
    },
    {
        $sort: { totalPoints: -1 }
    },
    {
        $group: {
            _id: null,
            docs: { $push: '$$ROOT' }
        }
    },
    {
        $set: {
            docs: {
                $map: {
                    input: {
                        $filter: {
                            input: '$docs',
                            as: 'x',
                            cond: { $eq: ['$$x._id', '1a3'] }
                        }
                    },
                    as: 'xx',
                    in: {
                        _id: '$$xx._id',
                        totalPoints: '$$xx.totalPoints',
                        rank: {
                            $add: [{ $indexOfArray: ['$docs._id', '1a3'] }, 1]
                        }
                    }
                }
            }
        }
    },
    {
        $unwind: '$docs'
    },
    {
        $replaceWith: '$docs'
    }
])

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