双重数组 $lookup 调用,保留原始结构。

huangapple go评论158阅读模式
英文:

Double array $lookup call preserving original structure

问题

我尝试在聚合中填充一个双重数组对象,所以我正在使用`$lookup`函数。集合看起来像这样:

{
  foo: [
    {
      bar: [
        {
          _id: ObjectId('63f508eedd2962118c37ea36')
        }
      ]
    }
  ]
}

我的lookup如下:

{
  $lookup: {
    from: "collection",
    localField: "foo.bar",
    foreignField: "_id",
    as: "foo.bar",
  },
}

这导致了以下结果:

{
foo: {
bar: [
{
_id: ObjectId('63f508eedd2962118c37ea36'),
field1: "helloworld"
}
]
}
}

而我实际想要的是:

{
foo: [
{
bar: [
{
_id: ObjectId('63f508eedd2962118c37ea36'),
field1: "helloworld"
}
]
}
]
}


有没有关于如何在聚合中实现我想要的效果的想法?

<details>
<summary>英文:</summary>

I&#39;m trying to populate a double array object but in an aggregate so I am utilizing the `$lookup` function. The collection looks something like this:

```BSON
{
  foo: [
    {
      bar: [
        {
          _id: ObjectId(&#39;63f508eedd2962118c37ea36&#39;)
        }
      ]
    }
  ]
}

My lookup looks like:

{
  $lookup: {
    from: &quot;collection&quot;,
    localField: &quot;foo.bar&quot;,
    foreignField: &quot;_id&quot;,
    as: &quot;foo.bar&quot;,
  },
}

which results in

{
  foo: {
    bar: [
      {
        _id: ObjectId(&#39;63f508eedd2962118c37ea36&#39;),
        field1: &quot;helloworld&quot;
      }
    ]
  }
}

where what I actually want is

{
  foo: [
    {
      bar: [
        {
          _id: ObjectId(&#39;63f508eedd2962118c37ea36&#39;),
          field1: &quot;helloworld&quot;
        }
      ]
    }
  ]
}

Any ideas on how to achieve what I want in an aggregate?

答案1

得分: 1

  1. $lookup - 使用$lookup来连接collection集合并返回bars数组字段。

  2. $set - 设置foo数组。

    2.1. $map - 遍历foo数组中的元素。

    2.1.1. $mergeObjects - 将当前迭代的foo元素与2.1.1.1.1的结果合并。

    2.1.1.1. 包含结果为2.1.1.1.1.1bar字段的文档。

    2.1.1.1.1. $map - 遍历bar数组中的元素。

    2.1.1.1.1.1. $mergeObjects - 将当前迭代的bar元素与2.1.1.1.1.1.1的结果合并。

    2.1.1.1.1.1.1. $first - 从bars数组中按_id匹配获取第一个元素。

  3. $unset - 移除bars数组。

英文:

Seems a direct map with $lookup for the nested array is not possible.

  1. $lookup - Join the collection collection and return the bars array field.

  2. $set - Set foo array.

    2.1. $map - Iterate element in foo array.

    2.1.1. $mergeObjects - Merge current iterated foo element with the result of 2.1.1.1.

    2.1.1.1. A document with a bar field which contains the result of 2.1.1.1.1.

    2.1.1.1.1. $map - Iterate element in bar array.

    2.1.1.1.1.1. $mergeObjects - Merge the current iterated bar element with the result of 2.1.1.1.1.1.1.

    2.1.1.1.1.1.1. $first - Get the first matching element from the bars array by _ids.

  3. $unset - Remove bars array.

db.from.aggregate([
  {
    $lookup: {
      from: &quot;collection&quot;,
      localField: &quot;foo.bar._id&quot;,
      foreignField: &quot;_id&quot;,
      as: &quot;bars&quot;
    }
  },
  {
    $set: {
      foo: {
        $map: {
          input: &quot;$foo&quot;,
          as: &quot;foo&quot;,
          in: {
            $mergeObjects: [
              &quot;$$foo&quot;,
              {
                bar: {
                  $map: {
                    input: &quot;$$foo.bar&quot;,
                    as: &quot;bar&quot;,
                    in: {
                      $mergeObjects: [
                        &quot;$$bar&quot;,
                        {
                          $first: {
                            $filter: {
                              input: &quot;$bars&quot;,
                              cond: {
                                $eq: [
                                  &quot;$$bar._id&quot;,
                                  &quot;$$this._id&quot;
                                ]
                              }
                            }
                          }
                        }
                      ]
                    }
                  }
                }
              }
            ]
          }
        }
      }
    }
  },
  {
    $unset: &quot;bars&quot;
  }
])

Demo @ Mongo Playground

答案2

得分: 1

也许在 foo 层级上首先使用 $unwind,然后执行 $lookup$group 会更简单?

db.from.aggregate([
  {
    "$unwind": "$foo"
  },
  {
    $lookup: {
      from: "collection",
      localField: "foo.bar._id",
      foreignField: "_id",
      as: "foo.bar"
    }
  },
  {
    $group: {
      _id: "$_id",
      foo: {
        $push: "$foo"
      }
    }
  }
])

Mongo Playground

英文:

Maybe it would be simpler to $unwind at foo level first, do the $lookup and $group back the result?

db.from.aggregate([
  {
    &quot;$unwind&quot;: &quot;$foo&quot;
  },
  {
    $lookup: {
      from: &quot;collection&quot;,
      localField: &quot;foo.bar._id&quot;,
      foreignField: &quot;_id&quot;,
      as: &quot;foo.bar&quot;
    }
  },
  {
    $group: {
      _id: &quot;$_id&quot;,
      foo: {
        $push: &quot;$foo&quot;
      }
    }
  }
])

Mongo Playground

huangapple
  • 本文由 发表于 2023年2月24日 09:27:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/75551861.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定