Создание представления с неагрегатным полем в mongodb без помещения его в поле _id

#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