Предположим, у меня есть коллекция с миллионами документов. Ниже приведен пример того, как выглядят документы
[
{ _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 и так далее.
как именно рассчитывается ранг? это позиция документа после сортировки по totalPoints?
@ĐĵΝιΓΞΗΛψΚ да. Общее количество баллов — это сумма баллов в массиве баллов. Ранг рассчитывается путем сортировки всех документов в порядке убывания. Первый документ становится рангом 1 и так далее.
получите их в порядке убывания и используйте .forEach
, добавив один, и если идентификатор является вашим идентификатором, верните его.
моя проблема не в использовании $group
. Моя проблема в том, что я хочу отсортировать все документы в коллекции и получить индекс данного документа в этой коллекции. Должен ли я запрашивать все документы, выполнять сортировку и получать индекс, или есть ярлык, который не включает запрос всех документов только для того, чтобы получить один?
конвейер агрегации, подобный следующему, может получить желаемый результат. но как он работает с коллекцией из миллионов документов, еще предстоит увидеть.
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'
}
])
Я смотрю на потоки изменений. Похоже, они могут решить мою проблему.