mongodb聚合-将数组的内容设置为输入,同时存储同级键 [英] mongodb aggregation - setting the contents of array as input, while storing sibling keys

查看:44
本文介绍了mongodb聚合-将数组的内容设置为输入,同时存储同级键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我有从上一步传递来的以下数据作为计数所有分支/树/林中的所有叶子"的输入时,我正处于聚合管道的中间.如以下问题所示:

只有当我直接从集合中阅读时,我才能正常工作.

我的问题是-我怎么能

  a)保存forest_ranger和some_other_data供以后使用";b)并通过将森林映射为的数组来开始下一阶段输入到计算所有叶子数"的文档? 

注意-我只是想让(b)为初学者工作,但是我似乎无法对待森林".数组,以便上面链接中的解决方案可以发挥作用.

然后-完成该阶段后,提取(a)中存储的内容,以获取所有计数的原始格式.

这是使用 $ group 的主要缺点.您必须使用 $ first $ last 像这样:

通过此新 MongoPlayground链接获取测试数据.

检查从链接获取的更新查询:

  db.Forests.aggregate([{$ unwind:" $ forests"},{$ unwind:" $ forests.trees"},{$ unwind:"$ forests.trees.branches"},{$ lookup:{来自:叶子",localField:"forests.trees.branches.branch_id",foreignField:"branch_id",如:"forests.trees.branches.leaves";}},{$ addFields:{"forests.trees.branches.leaf_count":{$ size:"$ forests.trees.branches.leaves"}}},{$ project:{" forests.trees.branches.leaves" ;: 0}},{$ group:{_ID: {forest_id:"$ forests.forest_id",tree_id:" $ forests.trees.tree_id"},forest_ranger:{$ first:" $ forest_ranger"},some_other_data:{$ first:" $ some_other_data"},leaf_count:{$ sum:"$ forests.trees.branches.leaf_count"},分支机构:{$ push:" $ forests.trees.branches"}}},{$ group:{_id:"$ _ id.forest_id",forest_ranger:{$ first:" $ forest_ranger"},some_other_data:{$ first:" $ some_other_data"},leaf_count:{$ sum:"$ leaf_count";},树木:{$ push:{leaf_count:{$ sum:"$ leaf_count";},tree_id:"$ _ id.tree_id",分支机构:"$ branches"}}}},{$ group:{_id:null,forest_ranger:{$ first:" $ forest_ranger"},some_other_data:{$ first:" $ some_other_data"},leaf_count:{$ sum:"$ leaf_count";},森林:{$ push:{leaf_count:{$ sum:"$ leaf_count";},forest_id:"$ _ id",树:"$ trees"}}}},{$ project:{_id:0}}]) 

输出:

 <代码> {"forest_ranger":"bob"," some_other_data":{数据":虚拟数据";},"leaf_count";:4森林":[{"leaf_count";:3"forest_id":"forestA",树":[{"leaf_count";:1"tree_id":"treeB",分支":[{"branch_id":"branchB","leaf_count";:1}]},{"leaf_count";:2"tree_id":"treeA",分支":[{"branch_id":"branchA","leaf_count";:1},{"branch_id":"branchA1","leaf_count";:1},{"branch_id":"branchA2","leaf_count";:0}]}]},{"leaf_count";:1"forest_id":"forestB",树":[{"leaf_count";:0,"tree_id":"treeD",分支":[{"branch_id":"branchD","leaf_count";:0}]},{"leaf_count";:1"tree_id":"treeC",分支":[{"branch_id":"branchC","leaf_count";:1}]}]},{"leaf_count";:0,"forest_id":"forestC",树":[{"leaf_count";:0,"tree_id":"treeE",分支":[{"branch_id":"branchE","leaf_count";:0}]}]}]} 

I'm in the middle of an aggregation pipeline when I have the following data passed from the previous step as input to a "count all leaves in all branches/trees/forests" as indicated in this question: Need guidance on mongo aggregate lookup to count subnodes in all child nodes for each node

{
    forest_ranger: "bob",
    some_other_data: {},
    forests: [
      {
        forest_id: 'forestA',
        trees: [
          {
            tree_id: 'treeA',
            branches: [
              {
                 branch_id: 'branchA',
              }
            ]
          }
        ]
      }
    ],
}

I have that all working properly, but only if I'm reading directly from a collection.

My question is - how can I

a)  save forest_ranger and some_other_data "for later"
b)  and start the next stage by mapping forests as the array of
    documents that are input to the "count all leaves"?

Note - I tried to get just (b) working for starters, but I can't seem to treat "forests" as an array so that the solution in the link above can do its magic.

Then- when that phase is done, extract what was stored in (a) to get the original format back with all the counts.

解决方案

That is the main disadvantage of using $group. You have to explicitly carry forward every non participating fields using either $first or $last like this:

Get the test data with those additional fields from this new MongoPlayground link.

Check the updated query taken from the link:

db.Forests.aggregate([
    { $unwind: "$forests" },
    { $unwind: "$forests.trees" },
    { $unwind: "$forests.trees.branches" },
    {
        $lookup: {
            from: "Leaves",
            localField: "forests.trees.branches.branch_id",
            foreignField: "branch_id",
            as: "forests.trees.branches.leaves"
        }
    },
    {
        $addFields: {
            "forests.trees.branches.leaf_count": { $size: "$forests.trees.branches.leaves" }
        }
    },
    {
        $project: { "forests.trees.branches.leaves": 0 }
    },
    {
        $group: {
            _id: {
                forest_id: "$forests.forest_id",
                tree_id: "$forests.trees.tree_id"
            },
            forest_ranger: { $first: "$forest_ranger" },
            some_other_data: { $first: "$some_other_data" },
            leaf_count: { $sum: "$forests.trees.branches.leaf_count" },
            branches: { $push: "$forests.trees.branches" }
        }
    },
    {
        $group: {
            _id: "$_id.forest_id",
            forest_ranger: { $first: "$forest_ranger" },
            some_other_data: { $first: "$some_other_data" },
            leaf_count: { $sum: "$leaf_count" },
            trees: {
                $push: {
                    leaf_count: { $sum: "$leaf_count" },
                    tree_id: "$_id.tree_id",
                    branches: "$branches"
                }
            }
        }
    },
    {
        $group: {
            _id: null,
            forest_ranger: { $first: "$forest_ranger" },
            some_other_data: { $first: "$some_other_data" },
            leaf_count: { $sum: "$leaf_count" },
            forests: {
                $push: {
                    leaf_count: { $sum: "$leaf_count" },
                    forest_id: "$_id",
                    trees: "$trees"
                }
            }
        }
    },
    {
        $project: { _id: 0 }
    }
])

Output:

{
    "forest_ranger" : "bob",
    "some_other_data" : {
        "data" : "Dummy data"
    },
    "leaf_count" : 4,
    "forests" : [
        {
            "leaf_count" : 3,
            "forest_id" : "forestA",
            "trees" : [
                {
                    "leaf_count" : 1,
                    "tree_id" : "treeB",
                    "branches" : [
                        {
                            "branch_id" : "branchB",
                            "leaf_count" : 1
                        }
                    ]
                },
                {
                    "leaf_count" : 2,
                    "tree_id" : "treeA",
                    "branches" : [
                        {
                            "branch_id" : "branchA",
                            "leaf_count" : 1
                        },
                        {
                            "branch_id" : "branchA1",
                            "leaf_count" : 1
                        },
                        {
                            "branch_id" : "branchA2",
                            "leaf_count" : 0
                        }
                    ]
                }
            ]
        },
        {
            "leaf_count" : 1,
            "forest_id" : "forestB",
            "trees" : [
                {
                    "leaf_count" : 0,
                    "tree_id" : "treeD",
                    "branches" : [
                        {
                            "branch_id" : "branchD",
                            "leaf_count" : 0
                        }
                    ]
                },
                {
                    "leaf_count" : 1,
                    "tree_id" : "treeC",
                    "branches" : [
                        {
                            "branch_id" : "branchC",
                            "leaf_count" : 1
                        }
                    ]
                }
            ]
        },
        {
            "leaf_count" : 0,
            "forest_id" : "forestC",
            "trees" : [
                {
                    "leaf_count" : 0,
                    "tree_id" : "treeE",
                    "branches" : [
                        {
                            "branch_id" : "branchE",
                            "leaf_count" : 0
                        }
                    ]
                }
            ]
        }
    ]
}

这篇关于mongodb聚合-将数组的内容设置为输入,同时存储同级键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆