首页 > 解决方案 > 如何过滤两层深度的数组的数组元素?

问题描述

在我的集合中,我有一个数组,里面有对象,里面有数组。我的数据如下所示:

{
  'settings': {
    'labourContributions': [
      {
        'show': True,
        'Accrual': True,
        '_id': ObjectId('abc'),
        'name': 'Holidays',
        'amount': 10,
        'target': [
          {
            'date': 2021-05-17T23: 00: 00.000+00: 00,
            'percent': 4.0
          },
          {
            'date': 2021-05-19T23: 00: 00.000+00: 00,
            'percent': 10.0
          }
        ]
      },
      {
        'show': True,
        'Accrual': True,
        '_id': ObjectId('abd'),
        'name': 'Taxes',
        'amount': 10,
        'target': [
          {
            'date': 2021-04-01T23: 00: 00.000+00: 00,
            'percent': 8.0
          },
          {
            'date': 2021-05-27T23: 00: 00.000+00: 00,
            'percent': 10.0
          }
        ]
      }
    ]
  }
}

我的目标是labourContributions根据某个匹配返回所有元素,但在labourContributions.target其中我只想要一个元素,根据其他匹配(假设percent> 5)。

尝试使用聚合管道进行此操作,我只能做到这一点:

c = collection.aggregate([
  {
    "$match": {
      "settings.labourContributions": {
        "$elemMatch": {
          "Accrual": True
        }
      }
    }
  },
  {
    "$project": {
      "settings.labourContributions.$.target": {
        "$filter": {
          "input": "$settings.labourContributions.$.target",
          "as": "contributions",
          "cond": {
            "$gt": [
              "$$contributions.percent",
              5
            ]
          }
        }
      }
    }
  }
])

我不认为$project舞台可以支持$数组切片。如何根据我更深的数组进行查询?

标签: mongodbaggregation-frameworkpymongo

解决方案


我不认为$project舞台可以支持$数组切片。如何根据我更深的数组进行查询?

您只能$在更新查询中使用位置,

  • $match你的两个条件都使用嵌套$elemMatch
  • $filter迭代循环并按条件labourContributions过滤主文档Accrual
  • $map迭代上述过滤文档的循环
  • $filter迭代数组循环target并过滤文档percent
  • $mergeObjects合并地图的当前对象和过滤后的target数组
c = collection.aggregate([
  {
    $match: {
      "settings.labourContributions": {
        $elemMatch: {
          Accrual: true,
          target: {
            $elemMatch: {
              percent: { $gt: 5 }
            }
          }
        }
      }
    }
  },
  {
    $project: {
      "settings.labourContributions": {
        $map: {
          input: {
            $filter: {
              input: "$settings.labourContributions",
              cond: { $eq: ["$$this.Accrual", true] }
            }
          },
          in: {
            $mergeObjects: [
              "$$this",
              {
                target: {
                  $filter: {
                    input: "$$this.target",
                    cond: { $gt: ["$$this.percent", 5] }
                  }
                }
              }
            ]
          }
        }
      }
    }
  }
])

操场


推荐阅读