在mongodb中使用多个$ lookup和聚合

时间:2017-04-26 14:21:21

标签: mongodb mapreduce mongodb-query aggregation-framework

我有三个系列,

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

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

    _build文档结构:

    {
        "_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的新手。

    提前致谢!!

1 个答案:

答案 0 :(得分:1)

您可以使用以下聚合。

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

  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"}}}
  ])