#javascript #node.js #mongodb #mongoose
Вопрос:
У меня есть результат запроса из запроса агрегации мангустов, который мне нужно дополнительно обработать или, в лучшем случае, сделать это в самой агрегации.
Агрегация выглядит следующим образом
result = await TokenBalance.aggregate([
{
$match: {
$and: [
{ ethervalue: { $gte: minBalance } },
{
ethervalue: { $lte: maxBalance }
}
]
}
},
{ $limit:limit }
])
Это возвращает массив объектов этого формата
{
"_id": "61013d6dda7d7c0015af5ccf",
"balances": [
{
"address": "0x1fc3ddeb035310930a444c0fa59c01618d5902af",
"symbol": "HBTC",
"balance": 5.21419339e-10,
"usdvalue": 0.000020969961637162402
},
{
"address": "0x1fc3ddeb035310930a444c0fa59c01618d5902af",
"symbol": "NSBT",
"balance": 1.258566,
"usdvalue": 27.427343477595258
},
{
"address": "0x1fc3ddeb035310930a444c0fa59c01618d5902af",
"symbol": "CRV",
"balance": 517.985955847106,
"usdvalue": 806.7017064052314
},
{
"address": "0x1fc3ddeb035310930a444c0fa59c01618d5902af",
"symbol": "USDT",
"balance": 0.003469,
"usdvalue": 0.003470159747979122
}
],
"address": "0x1fc3ddeb035310930a444c0fa59c01618d5902af",
"ethervalue": 0.7604598621232733,
"createdAt": "2021-07-28T11:20:13.927Z",
"updatedAt": "2021-07-28T11:20:13.927Z",
"__v": 0
},
Что мне нужно, так это свойство «балансы», которое будет обрабатываться как сгруппированное по символу, и для каждого из этих символов суммируйте поля «Баланс» и «Значение usd».
Я бы предпочел, чтобы это было сделано в агрегации, если это возможно, но я, похоже, не могу сделать это правильно, даже не в чистых узлах.
Я хочу, чтобы результат был таким:
[
{
symbol: USDC, balance: xxx, usdvalue: yyy
},
{
symbol: USDT, balance: zzz, usdvalue: jjj
}
]
Ответ №1:
Вы можете использовать следующий подход,
$unwind
для деконструкцииbalances
массива$group
поsymbol
сумме иbalance
usdvalue
$addFields
чтобы переименовать_id
поле вsymbol
и и удалить_id
поле
result = await TokenBalance.aggregate([
{
$match: {
$and: [
{ ethervalue: { $gte: minBalance } },
{ ethervalue: { $lte: maxBalance } }
]
}
},
{ $unwind: "$balances" },
{
$group: {
_id: "$balances.symbol",
balance: { $sum: "$balances.balance" },
usdvalue: { $sum: "$balances.usdvalue" }
}
},
{
$addFields: {
symbol: "$_id",
_id: "$REMOVE"
}
},
{ $limit:limit }
])
Комментарии:
1. Спасибо. Я ограничил результаты этого запроса 5 объектами, и на его завершение ушло почти 8 минут. Не могли бы вы найти какие-либо способы улучшить это или способы выяснить, почему это занимает так много времени?
2. Я не уверен, сколько документов у вас в коллекции? а максимальное количество документов в
balances
массиве?3. коллекция tokenbalances сейчас содержит 3844656 документов. Вот почему я хотел ограничить его минимальными и максимальными значениями эфира. Массив балансов может содержать до 200 объектов, но в основном они находятся в среднем на 15-20.
4. 1) для улучшения процесса сканирования вы можете создать единый индекс на
ethervalue
поле, 2) он улучшится, если вы добавите этап $limit для основных документов после этапа $match и до этапа $unwind.5. Я постараюсь, что большое вам спасибо за это сейчас