【问题标题】:Using multiple $lookup with aggregation in mongodb在 mongodb 中使用多个 $lookup 和聚合
【发布时间】:2017-04-27 04:43:08
【问题描述】:

我有三个系列,

  1. _project - 它包含所有项目
  2. _build - 它包含所有构建并且每个构建都必须属于一个项目
  3. _build.details - 它包含必须属于一个广告集的广告,每个广告集必须属于一个广告系列,每个广告系列必须属于一个版本。

_项目文件结构:

{
    "_id" : ObjectId("58d8c501be2bee2bc0b3b081"),
    "CreatedBy" : ObjectId("58c801c606f72508d87421c6"),
    ....
    ....
},...

_构建文档结构:

{
    "_id" : ObjectId("58ee6c5e06f7254454a554fe"),
    "ModifiedBy" : ObjectId("58d93a98c6e7dbe94582619a"),
    "CreatedBy" : ObjectId("58d93a98c6e7dbe94582619a"),
    "ProgramId" : ObjectId("58c801b706f72508d87421c4"),
    "ProjectId" : ObjectId("58d9411ebe2bee43ec22aff6"),
    ....
    ....
},...

_build.detials 文档结构:

{
    "_id" : ObjectId("58de834cc6e7dbe945acf890"),
    "BuildId" : ObjectId("58ef4b95c6e7dbe945ba700b"),
    "Values" : null,
    "Headers" : null,
    "Data" : {
        "Campaign Name" : "Remarketing | Remarketing | Facebook | Conversions | 03-01-2017",
        "Ad Set Name" : "Cancelled Orders_Greater than 50%-Cancelled Orders_Less than 50% | Desktop | Feed | Female | 21-65",
        "Ad Name" : "Carousel | Draw1,Excited2,Lottery5,Beach4 | S:1814082498827964 | 03-01-2017 | 70Custom Audiences | ",
        "Ad Set Run Status" : "ACTIVE",
        "Ad Status" : "ACTIVE",
        "Campaign Objective" : "Conversions",
        "Gender" : "Female",
        "Age Min" : "21",
        "Age Max" : "65",

    },
    "Status" : false,
    "CampaignName" : "Remarketing | Remarketing | Facebook | Conversions | 03-01-2017",
    "AdSetName" : "Cancelled Orders_Greater than 50%-Cancelled Orders_Less than 50% | Desktop | Feed | Female | 21-65",
    "AdName" : "Carousel | Draw1,Excited2,Lottery5,Beach4 | S:1814082498827964 | 03-01-2017 | 70Custom Audiences | ",
    "Campaign_Status" : 1,
    "Campaign_Id" : "1",
    "Adset_Status" : 1,
    "Adset_Id" : "123",
    "Ad_Status" : 1,
    "Ad_Id" : "1234"
},...

我想要的查询:

我想从 _project 集合中获取所有项目,并希望针对每个项目进行构建,然后我想要针对每个项目和构建组合的广告、广告集和活动及其计数。

想要输出类似:

{
    "ProjectId" : ObjectId("58d8c501be2bee2bc0b3b081"),
    "BuildId" : ObjectId("5a5ads501basdadsc0b3b346"),
    "uniqueAdsCount" : "25",
    "uniqueAdsetCount" : "5",
    "uniqueCampaignCount" : "2",
    "uniqueAdNames":[

     ],
    "uniqueAdSetNames":[

     ],
    "uniqueCampaignNames":[

     ]
},
{
next project
},
{
next project
}...

到目前为止我做了什么:

db.getCollection('_build').aggregate([
    {
        $lookup:{
            from: "_project",
            localField: "ProjectId",
            foreignField: "_id",
            as: "result"
        }
   },
   {
        $project:{
            _id: 0,
            BuildId: "$_id",
            ProjectId: "$result._id"
       }
   },
   {
        $lookup:{
            from: "_build.detail",
            localField: "BuildId",
            foreignField: "BuildId",
            as: "resultS2"
        }
   },
   {
        $project:{
            BuildId: "$BuildId",
            ProjectId: "$ProjectId",
            adsCount: {$size: "$resultS2.AdName"},
            adSetCount: {$size: "$resultS2.AdSetName"},
            campaignCount: {$size: "$resultS2.CampaignName"},
        }
   }
]);

我尝试添加一个小组阶段并使用 $addToSet 但它在广告集中给了我重复,我不知道我做错了什么:

db.getCollection('_build').aggregate([
    {
        $lookup:{
            from: "_project",
            localField: "ProjectId",
            foreignField: "_id",
            as: "result"
        }
   },
   {
        $project:{
            _id: 0,
            BuildId: "$_id",
            ProjectId: "$result._id"
       }
   },
   {
        $lookup:{
            from: "_build.detail",
            localField: "BuildId",
            foreignField: "BuildId",
            as: "resultS2"
        }
   },
   {
        $project:{
            BuildId: "$BuildId",
            ProjectId: "$ProjectId",
            adsCount: {$size: "$resultS2"},
            ads: "$resultS2"
        }
   },
   {
        $group:{
            _id: "$BuildId",
            UniqueAds: {$addToSet: "$ads.Data.Ad Name"},
            UniqueAdsets: {$addToSet : "$ads.Data.Ad Set Name"}
        }
   }
]);

请帮忙,如有任何疑问,请告诉我,可能是我使用了完全错误的方法,我是 mongodb 的新手。

提前致谢!!

【问题讨论】:

  • 只是好奇。这个问题与stackoverflow.com/questions/42418336/… 不同,只是您现在将数据存储在联合集合中吗?
  • 是的,同样的问题,但是这次数据模型非常不同,我有项目和构建,并且在里面我有广告、广告集和活动,我在 _build.details 集合中没有 ProjectId ,但我想要基于项目的所有统计数据

标签: mongodb mapreduce mongodb-query aggregation-framework


【解决方案1】:

您可以使用以下聚合。

$group,在每个级别获取distinct 名称值,然后是$addFields 中的$size

  db.getCollection('_project').aggregate([
     {$lookup:{from: "_build",localField: "_id",foreignField: "ProjectId",as:"result"}},
     {$unwind:"$result"},
     {$project:{_id:0,ProjectId:"$_id",BuildId:"$result._id"}},
     {$lookup:{from:"_build.detail",localField:"BuildId",foreignField:"BuildId",as:"resultS2"}},
     {$unwind:"$resultS2"},
     {$group:{
    _id:{ProjectId:"$ProjectId", BuildId:"$BuildId",campaignName:"$resultS2.Data.Campaign Name",adSet:"$resultS2.Data.Ad Set Name"},
    uniqueAdNames:{$addToSet:"$resultS2.Data.Ad Name"}
        }
     },
     {$addFields:{uniqueAdsCount:{$size:"$uniqueAdNames" }}},
     {$group :{
     _id:{ProjectId:"$_id.ProjectId",BuildId:"$_id.BuildId",campaignName:"$_id.campaignName"},
     uniqueAdNames:{$first:"$uniqueAdNames"},
     uniqueAdsCount:{$first:"$uniqueAdsCount"},
     uniqueAdSets:{$addToSet:"$_id.adSet"}
        }
     },
     {$addFields:{uniqueAdsetCount:{$size:"$uniqueAdSets"}}},
     {$group:{
     _id:{ProjectId:"$_id.ProjectId",BuildId:"$_id.BuildId"},
     uniqueAdNames:{$first:"$uniqueAdNames"},
     uniqueAdsCount:{$first:"$uniqueAdsCount"},
     uniqueAdSetNames:{$first:"$uniqueAdSets"},
     uniqueAdsetCount:{$first:"$uniqueAdsetCount"},
     uniqueCampaignNames:{$addToSet:"$_id.campaignName"}
        }
     },
     {$addFields:{uniqueCampaignCount:{$size : "$uniqueCampaignNames"}}}
  ])

【讨论】:

  • 这太棒了。好吧,这看起来很大,但是现在我至少能够理解您的答案背后的逻辑。非常感谢。
  • 不客气。它只是$addToSet$first 保留旧值和$size $group + $project 中每个级别的运算符。如果您使用 3.4 版本,则可以使用 $addFields 来简化它。
  • 我正在尝试使用您之前的答案stackoverflow.com/questions/42418336/… 为我自己准备另一个查询,我想在这里分享它,并希望您调查一下并告诉我我的方法是对还是错。
  • 是的,我使用的是 3.4
  • 如果您不介意,您可能应该提出一个新问题或至少使用旧问题。我添加了 3.4 个编辑。
猜你喜欢
  • 2017-10-08
  • 2020-08-02
  • 2019-01-21
  • 1970-01-01
  • 2022-01-05
  • 1970-01-01
  • 2021-04-11
  • 1970-01-01
  • 2023-03-09
相关资源
最近更新 更多