#mongodb #aggregation-framework #pipeline
#mongodb #структура агрегации #конвейер
Вопрос:
У меня есть коллекция с данными, приведенными ниже
{
"_id" : ObjectId("5fc8a58257f6526c6a520725"),
"job_id" : ObjectId("5fc8a5822aed5820240c2893"),
"access_id" : ObjectId("5eda0b2495b51c1d746db8b2"),
"campaign_num" : "488707373",
"partner_id" : ObjectId("5a94e02bb0445b1cc742d735"),
"parent_partner" : ObjectId("5a8d70c4b0445b6a883fd395"),
"status" : "A",
"route" : "SR",
"otp" : true,
"trans" : false,
"job_payload" : {
"senderid" : "36",
"msisdn" : "9671660999",
"script" : "Your verification code is : 166297",
"pingbackurl" : "https://xyztesting.com/sms/v1/notify/pr/index.php",
"templateid" : "769",
"smstype" : "2"
},
"track" : {
"added" : {
"date" : ISODate("2020-12-03T08:44:50.000Z")
},
"routed" : ISODate("2020-12-03T08:44:50.000Z")
},
"message_parts" : 1,
"provider_status" : {
"job_id" : "",
"count" : {
"total" : 1,
"sent" : 0,
"delivered" : 0,
"failed" : 0
},
"delivery" : []
}
}
Я хотел подсчитать все итоги, отправленные, доставленные, неудачные, где campaign_num и date были одинаковыми. т.е. с использованием того же campaign_num и в ту же дату.
Я создал представление, используя приведенный ниже запрос
var pipeline = [
{
$group: {
_id: {
campaign: "$campaign_num",
date: { $dateToString: { format: "%Y-%d-%m", date: "$track.added.date" } }
},
total: { $sum: "$provider_status.count.total" },
sent: { $sum: "$provider_status.count.sent" },
delivered: { $sum: "$provider_status.count.delivered" },
failed: { $sum: "$provider_status.count.failed" }
}
}
]
db.createView("sms_daily_test","col_outbox",pipeline)
Я получаю результат, как показано ниже
"_id" : {
"campaign" : "488707373",
"date" : "2021-19-01"
},
"total" : 3,
"sent" : 3,
"delivered" : 0,
"failed" : 0
}
Теперь основная проблема заключается в том, что я хочу также включить поля partner_id и access_id, но не внутри _id. т.е. я хочу, чтобы результат был примерно таким
"_id" : {
"campaign" : "488707373",
"date" : "2021-19-01"
},
"total" : 3,
"sent" : 3,
"delivered" : 0,
"failed" : 0,
"partner_id":ObjectId("5a94e02bb0445b1cc742d735"),
"access_id":ObjectId("5a94e02bb0445b1cc742d635")
}
Я использую приведенный ниже код для этой цели
var pipeline = [
{
$group: {
_id: {
campaign: "$campaign_num",
date: { $dateToString: { format: "%Y-%d-%m", date: "$track.added.date" } }
},
partner_id: "$partner_id",
access_id: "$access_id",
total: { $sum: "$provider_status.count.total" },
sent: { $sum: "$provider_status.count.sent" },
delivered: { $sum: "$provider_status.count.delivered" },
failed: { $sum: "$provider_status.count.failed" }
}
}
]
db.createView("sms_daily_testing2","col_outbox",pipeline)
Когда я запускаю его, я получаю следующее сообщение об ошибке:
The field 'partner_id' must be an accumulator object
.
Информация об этом поле заключается в том, что у конкретной кампании будет только один partner_id
и один access_id
. Хотя у a partner_id
может быть несколько кампаний, а у a access_id
также может быть несколько кампаний.
Мне нужно сгруппировать данные по кампаниям и полю даты, что я и сделал. Мне просто нужно знать, как добавить эти два поля, не помещая их во внутреннее _id
поле.
Ответ №1:
Вы написали, что у данной кампании и даты будут уникальные идентификаторы партнеров и access_id. И мы должны использовать объект-накопитель вне поля _id. Поскольку у нас есть только один партнер и access_id, мы можем использовать $first или $last, как показано :
var pipeline=[{$group:{_id:{campaign:"$campaign_num",date:{$dateToString:{format:"%Y-%m-%d",date:"$track.added.date"}}},
partner_id:{$first:"$partner_id"},
access_id:{$first:"$access_id"},
total: {$sum: "$provider_status.count.total"},
sent:{$sum:"$provider_status.count.sent"},
delivered:{$sum:"$provider_status.count.delivered"},
failed:{$sum:"$provider_status.count.failed"}}
}]
Ответ №2:
Используйте это:
var pipeline = [
{
$group: {
_id: {
campaign: "$campaign_num",
date: { $dateToString: { format: "%Y-%d-%m", date: "$track.added.date" } }
},
partner_id: { $push: "$partner_id" },
access_id: { $push: "$access_id" },
total: { $sum: "$provider_status.count.total" },
sent: { $sum: "$provider_status.count.sent" },
delivered: { $sum: "$provider_status.count.delivered" },
failed: { $sum: "$provider_status.count.failed" }
}
}
]
Вместо $push
вы также можете использовать $addToSet