【问题标题】:Project and filter using elemMatch on child elements在子元素上使用 elemMatch 进行投影和过滤
【发布时间】:2022-01-14 15:08:11
【问题描述】:

这是我收藏的内容:

[{
  "_id": {
    "$oid": "61b253a89e51973f978b818d"
  },
  "id": 1,
  "level1": [
    {
      "name": "child11",
      "level2": [
        {
          "name": "chil21"
        },
        {
          "name": "chilxx"
        }
      ]
    },
    {
      "name": "child12",
      "level2": [
        {
          "name": "chil23"
        },
        {
          "name": "chil24"
        }
      ]
    }
  ]
},{
  "_id": {
    "$oid": "61b254b69e51973f978b818e"
  },
  "id": 2,
  "level1": [
    {
      "name": "child13",
      "level2": [
        {
          "name": "chil25"
        },
        {
          "name": "chil26"
        }
      ]
    },
    {
      "name": "child14",
      "level2": [
        {
          "name": "chil27"
        },
        {
          "name": "chil28"
        },
        {
          "name": "chilxx"
        },
        {
          "name": "chil2a"
        }
      ]
    }
  ]
}]

我现在想聚合这样的

  • 聚合文档与集合中的原始文档具有相同的结构
  • level1 数组仅包含本身包含level2 元素和name = chilxx 的元素

因此,预期的聚合输出应该是:

[{
  "_id": {
    "$oid": "61b253a89e51973f978b818d"
  },
  "id": 1,
  "level1": [
    {
      "name": "child11",
      "level2": [
        {
          "name": "chil21"
        },
        {
          "name": "chilxx"
        }
      ]
    }
  ]
},{
  "_id": {
    "$oid": "61b254b69e51973f978b818e"
  },
  "id": 2,
  "level1": [
    {
      "name": "child14",
      "level2": [
        {
          "name": "chil27"
        },
        {
          "name": "chil28"
        },
        {
          "name": "chilxx"
        },
        {
          "name": "chil2a"
        }
      ]
    }
  ]
}]

这是我的(不工作的)聚合方法:

[
  {
    '$match': {}
  }, {
    '$project': {
      '_id': 1, 
      'id': 1, 
      'level1': {
        '$filter': {
          'input': '$level1', 
          'as': 'l1', 
          'cond': {
            '$$l1.level2': {
              '$elemMatch': {
                'name': 'chilxx'
              }
            }
          }
        }
      }
    }
  }
]

但是,这会导致错误:

Invalid $project :: caused by :: Unrecognized expression '$$l1.level2'

提前谢谢你。

【问题讨论】:

    标签: arrays mongodb filter aggregation-framework


    【解决方案1】:
    • $match
    • $set
    db.collection.aggregate([
      {
        "$match": {
          "level1.level2.name": "chilxx"
        }
      },
      {
        "$set": {
          "level1": {
            "$filter": {
              "input": "$level1",
              "as": "first",
              "cond": {
                $ne: [
                  {
                    "$filter": {
                      "input": "$$first.level2",
                      "as": "second",
                      "cond": {
                        $eq: [
                          "$$second.name",
                          "chilxx"
                        ]
                      }
                    }
                  },
                  []
                ]
              }
            }
          }
        }
      }
    ])
    

    mongoplayground

    【讨论】:

    • 太棒了。我从中学到了两件事。 $set 可以更容易地保持原始结构,并且可以使用 $ne 排除空列表。我将您的答案应用于我的(更复杂的)结构,它按预期工作。
    猜你喜欢
    • 1970-01-01
    • 2014-10-21
    • 2015-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-04
    • 1970-01-01
    相关资源
    最近更新 更多