Есть ли способ вернуть определенные вложенные поля из запроса в MongoDB?
Есть ли способ получить сумму денег, выплаченную в зависимости от категории спорта? Это не может быть ограничено только "Джоном", но во всех документах коллекции.
Ожидаемый запрос возврата для предоставленных данных:
{
{"Fight": [100,95] },
{"Running": [50] }
}
Пример данных:
{"_id":"5z621578b0ce483b9866fb1f",
"Name":"John",
"Sports":[
{"Category":"Fight",
"Billing":[
{"Month":"Jan",
"Status":"Paid",
"Price":100},
{"Month":"Feb",
"Status":"Not Paid",
"Price":125},
{"Month":"Mar",
"Status":"Paid",
"Price":95}
]
},
{"Category":"Running",
"Billing":[
{"Month":"Jan",
"Status":"Not Paid",
"Price":200},
{"Month":"Feb",
"Status":"Paid",
"Price":50}
]
}
]
}
Другими словами: мне нужно сравнить статус биллинга внутри каждого вложенного объекта и проверить, является ли он "Оплаченным", а затем, если true, добавить соответствующий объект биллинга "Цена" в соответствующий массив " Вид спорта".
Для всех документов в коллекции, с несколькими спортивными категориями и несколькими месяцами выставления счетов. Но всегда одна и та же вложенная структура.
Заранее спасибо!
1 ответ
Как сказал Уиллис в своем комментарии, вы можете использовать агрегацию: https://docs.mongodb.com/manual/aggregation/
Следующая агрегация даст вам данные, которые вы ищете (замените счета фактическим названием вашей коллекции):
db.billings.aggregate([
{ $unwind: '$Sports'},
{ $unwind: '$Sports.Billing'},
{ $match: { 'Sports.Billing.Status': 'Paid' } },
{
$group: {
_id: '$Sports.Category',
Category: {$first: '$Sports.Category'},
Prices: { $push: '$Sports.Billing.Price' }
}
},
{ $project: {_id: 0} }
]);
Результат этой агрегации будет выглядеть примерно так:
[
{
"Category" : "Running",
"Prices" : [
50.0
]
},
{
"Category" : "Fight",
"Prices" : [
100.0,
95.0
]
}
]
Точный формат, который вы запросили в своем вопросе, немного ненормальный; на мой взгляд, я думаю, что было бы лучше сохранить его в форме агрегации выше результатов. Но если вы хотите получить такую форму, как в вопросе, агрегация будет немного более сложной:
db.billings.aggregate([
{ $unwind: '$Sports'},
{ $unwind: '$Sports.Billing'},
{ $match: { 'Sports.Billing.Status': 'Paid' } },
{
$group: {
_id: '$Sports.Category',
Prices: { $push: '$Sports.Billing.Price' }
}
},
{
$group: {
_id: 0,
Sports: { $push: { Category: '$_id', Prices: '$Prices' } }
}
},
{
$project: {
Sports: {
$arrayToObject: {
'$map': {
'input': '$Sports',
'as': 'el',
'in': {
'k': '$$el.Category',
'v': '$$el.Prices'
}
}
}
}
}
},
{ $replaceRoot: { newRoot: '$Sports'} }
]);