【发布时间】:2021-04-14 19:00:36
【问题描述】:
我需要通过来自engagements 和broadcastreports 的相同coordinates 字段在一个名为location 的数组中进行分组。此外,如果一个coordinate 存在于一个中而另一个上不存在,则无论如何都应该包含它。
在该数组中,我需要包含一个scans,它是与campaign_ad_group 相关的engagements 的数量,以及一个impressions 字段,它是与campaign_ad_group 相关的broadcastreports.analytics.impressions 的总和。
我有以下聚合:
.aggregate([
{
$match: {
'_id': ObjectId("60520e1d09ba3a769ab85f68"),
}
},
{
$project: {
'_id': 1,
'broadcasts_to': 1
}
},
{
$lookup: {
from: 'campaignadgroups',
localField: '_id',
foreignField: 'campaign_id',
as:'campaign_ad_group'
}
},
{
$unwind: '$campaign_ad_group'
},
{
$lookup: {
from: 'broadcastplans',
let: { 'campaign_ad_group_id': '$campaign_ad_group._id' },
as: 'broadcastplans',
pipeline: [
{
$match: {
$expr: {
$eq: ['$campaign_ad_group_id','$$campaign_ad_group_id' ]
}
}
},
{ $project: { '_id': 1 } }
]
}
},
// Above it's only the necessary data gathering to get the needed engagements and broadcastreports.
{
$lookup: {
from: 'engagements',
let: { 'broadcastplan_ids': '$broadcastplans._id' },
as: 'engagements',
pipeline: [
{
$match: {
$expr: {
$and: [
{ $in: ['$broadcast_plan_id', '$$broadcastplan_ids'] },
{ $gte: ['$reported_at', ISODate('2019-12-29T15:02:47.305Z')] },
{ $lte: ['$reported_at', ISODate('2021-12-29T15:02:47.305Z')] }
]
}
}
}
]
}
},
{
$unwind: '$engagements'
},
{
$group: {
'_id': {
'adgroup_id': '$campaign_ad_group._id',
'coordinates': '$engagements.location.coordinates',
},
'adgroup_name': {$first: '$campaign_ad_group.name'},
'scans': {$sum: 1}
}
},
{
$group: {
'_id': '$_id.adgroup_id',
'name': {$first: '$adgroup_name'},
'location': {
$push: {
'scans': '$scans',
'coordinates': '$_id.coordinates'
}
}
}
}
])
我得到的输出如下:
{
"_id" : ObjectId("5fe9f89f603eaa22b3d374f5"),
"name" : "Sick name",
"location" : [
{
"scans" : 1.0,
"coordinates" : [
-8.63294964028813,
56.1520268933931
]
},
{
"scans" : 1.0,
"coordinates" : [
-9.63294964028813,
58.1520268933931
]
}
]
}
现在是我卡在的部分。我需要查找集合broadcastreports 并按其坐标与engagements 坐标进行分组,并包含一个字段impressions,它是broadcastreports.analytics.impressions 的总和。
通过删除group 管道并从broadcastreports 中查找,它将如下所示:
.aggregate([
.
. // ABOVE IS THE SAME DATA GATHERING AS BEFORE
.
{
$lookup: {
from: 'engagements',
let: { 'broadcastplan_ids': '$broadcastplans._id' },
as: 'engagements',
pipeline: [
{
$match: {
$expr: {
$and: [
{ $in: ['$broadcast_plan_id', '$$broadcastplan_ids'] },
{ $gte: ['$reported_at', ISODate('2019-12-29T15:02:47.305Z')] },
{ $lte: ['$reported_at', ISODate('2021-12-29T15:02:47.305Z')] }
]
}
}
}
]
}
},
{
$lookup: {
from: 'broadcastreports',
let: { 'broadcastplan_ids': '$broadcastplans._id' },
as: 'broadcastreports',
pipeline: [
{
$match: {
$expr: {
$and: [
{ $in: ['$broadcast_plan_id', '$$broadcastplan_ids'] },
{ $gte: ['$reported_at', ISODate('2019-12-29T15:02:47.305Z')] },
{ $lte: ['$reported_at', ISODate('2021-12-29T15:02:47.305Z')] }
]
}
}
}
]
}
},
])
这让我得到了我需要的所有数据,例如:
{
_id: ObjectId("60520e1d09ba3a769ab85f68"),
campaign_ad_group: {
_id: ObjectId("5fc1215a039674c600c0f533"),
name: 'Sick name'
},
broadcastplans: [_ids],
engagements: [
{
_id,
coordinates: [-9.63294964028813,58.1520268933931],
reported_at: Date
},
{
_id,
coordinates: [-8.63294964028813,56.1520268933931],
reported_at: Date
}
],
broadcastreports: [
{
_id,
coordinates: [-9.63294964028813,58.1520268933931],
reported_at: Date,
analytics: {
impressions: 10
}
},
{
_id,
coordinates: [-5.20923334343244,40.4874833434234],
reported_at: Date,
analytics: {
impressions: 5
}
}
]
}
我需要以一种我得到以下输出的方式对它进行分组:
[
{
_id: campaign_ad_group._id,
name: campaign_ad_group.name,
location: [
{
scans: 1,
impressions: 10,
coordinates: [-9.63294964028813,58.1520268933931]
},
{
scans: 0, // This coordinate does not exist on the engagements so its 0 but needs to be
// included anyway.
impressions: 5,
coordinates: [-5.20923334343244,40.4874833434234]
},
{
scans: 1,
impressions: 0, // Same here
coordinates: [-8.63294964028813,56.1520268933931]
},
]
}
]
【问题讨论】:
标签: mongodb aggregation-framework