【问题标题】:MongoDB Aggregation - $filter in projection for embedded arraysMongoDB 聚合 - 嵌入式数组的投影中的 $filter
【发布时间】:2021-03-07 04:08:57
【问题描述】:

我有一个复杂的 JSON 对象结构,其中包含 (N) 个嵌入式数组。单个条目是具有两个字段的对象:@namecontent。我需要在投影阶段过滤它们(不使用$unwind)以获得@name字段等于特定值的特定对象:

 productCategory: {$filter: {
 input: '$characteristics.attributeGroup.attribute',
 as: 'attribute',
 cond: {
        ...?
 }}

$characteristics.attributeGroup.attribute 输入返回上述结构。我试图在$cond: { $eq: ['$$attribute.@name', 'averageRating'] } 中使用类似的东西,但它不起作用。

您能帮我在这里找到解决方案吗?

提前致谢!

【问题讨论】:

  • 您可以添加一些示例文档而不是图像以及您想要的预期结果吗?在对象或数组中?
  • 这是示例 json 内容:pastebin.com/8er3iPMB 预期结果将只是具有该搜索名称的对象,或者至少是具有单个条目的数组。例如:属性:{“@name”:“attributeKey2”,“内容”:“attributeValue2”}
  • @name 属性值是唯一的。不能在任何其他数组/对象中重复
  • 你能添加预期的输出吗?这会让事情变得简单

标签: arrays mongodb aggregation-framework projection


【解决方案1】:

你可以试试,

  • $reduce 迭代 attributeGroup 数组的循环,并使用 $mergeObjects 反向合并对象
  • 检查条件如果属性的类型是object 然后再次检查第二个条件如果@name 匹配然后返回值,否则移动到其他条件
  • $reduce 迭代 attribute 数组的循环,检查条件如果名称匹配则返回值
let name = "Artikelhinweise";
db.collection.aggregate([
  { $match: { "attributeGroup.attribute.@name": name } }, // name pass here
  {
    $project: {
      attributeGroup: {
        $reduce: {
          input: "$attributeGroup",
          initialValue: {},
          in: {
            $mergeObjects: [
              "$$value",
              {
                $cond: [
                  { $eq: [{ $type: "$$this.attribute" }, "object"] },
                  {
                    $cond: [
                      { $eq: ["$$this.attribute.@name", name] }, // name pass here
                      {
                        "@name": "$$this.attribute.@name",
                        "content": "$$this.attribute.content"
                      },
                      "$$value"
                    ]
                  },
                  {
                    $reduce: {
                      input: "$$this.attribute",
                      initialValue: {},
                      in: {
                        $cond: [
                          { $eq: ["$$this.@name", name] }, // name pass here
                          {
                            "@name": "$$this.@name",
                            "content": "$$this.content"
                          },
                          "$$value"
                        ]
                      }
                    }
                  }
                ]
              }
            ]
          }
        }
      }
    }
  }
])

Playground

【讨论】:

  • 嘿Turivishal!谢谢您的回答。我试图将该阶段应用于更多“类似产品”的数据。似乎该结构比我预期的要嵌入一些。我在 mongo 操场上创建了一个新配置:mongoplayground.net/p/m9mwDIeXWRn 那个顶级数组是以前的“productAttributes”值,但似乎还有额外的 attributeGroup 数组:/ 其余的都是相同的,包括对象中的 @name 和 content 字段,但是经过研究,我仍然无法在 @name 字段中使用 Produktbasisklasse 提取单个字段
  • 在某些文档中,attribute 字段是对象,而在某些其数组中,是正确的数据,还是 attribute 字段具有两种类型的数据?
  • 没错。如果有超过 1 个属性 - 它是一个数组,但只有一个 - 一个 json 对象:/
  • 我已经更新了答案和操场链接,你可以检查一下。您需要在 3 个位置传递名称值进行搜索。正如我在代码中评论的那样。
猜你喜欢
  • 2019-10-23
  • 1970-01-01
  • 1970-01-01
  • 2015-05-12
  • 1970-01-01
  • 1970-01-01
  • 2014-05-04
  • 2015-09-08
  • 1970-01-01
相关资源
最近更新 更多