mongodb使用聚合过滤多级嵌套数组

问题描述 投票:0回答:2

我有一个数组:

[
  {
    id: 1,
    name: 1,
    list: [
      {
        id: 11,
        name: 11,
        list: [
          [
            { id: 111, name: 111 },
            { id: 112, name: 112 }
          ]
        ]
      }
    ]
  },
  {
    id: 6,
    name: 6,
    list: [
      {
        id: 62,
        name: 12,
        list: [ [ { id: 111, name: 111 } ] ]
      }
    ]
  }
]

希望过滤二级列表数组,使用命令如下

{
  $project: {
    id: 1, name: 1,
    list: {
      id: 1, name: 1,
      list: {
        $filter: {
          input: '$list.list',
          as: 'item',
          cond: { $eq: ['$$item.name', 111] }
        }
      }
    }
  }
}

却没有得到预期的结果。完整的过滤器代码如下:

db.runoob.aggregate([{ $match: { $or: [{ 'name': 1, 'list.name': { $eq: 11 } }, { name: 6, 'list.name': { $eq: 12 } }] } }, { $project: { id:1, name: 1, 'list': { $filter: { input: '$list', as: 'item', cond: { $or: [{ $and: [{ $in: ['$$item.id', [11, 12]] }, {$eq: ['$$item.name', 11]}] }, { $and: [{ $in: ['$$item.id', [61, 62]] }, {$eq: ['$$item.name', 12]}] }] } } } } }, { $project: { id: 1, name: 1, list: { id: 1, name: 1, list: { $filter: { input: '$list.list', as: 'item1', cond: { $eq: ['$$item1.name', 111] } } } } } }])

请帮帮我,谢谢^_^

我尝试使用 $unwind 如下

db.runoob.aggregate([{ $unwind: '$list' }, { $unwind: '$list.list' }, { $unwind: '$list.list.list' }, { $match: { $or: [{ 'name': 1, 'list.name': { $eq: 11 }, 'list.list.name': { $eq: 112 } }, { name: 6, 'list.name': { $eq: 12 } }] } } ])

但是这个命令会破坏结构

希望保留原来的数据结构,或者使用$unwind后还有其他方法恢复结构

mongodb aggregate
2个回答
0
投票

参考本文内容:在此输入链接描述

我尝试编写如下代码:

db.collection.aggregate([
  {
    $match: {
      $or: [
        {
          "name": 1,
          "list.name": {
            $eq: 11
          }
        },
        {
          name: 6,
          "list.name": {
            $eq: 12
          }
        }
      ]
    }
  },
  {
    $project: {
      id: 1,
      name: 1,
      "list": {
        $filter: {
          input: "$list",
          as: "item",
          cond: {
            $or: [
              {
                $and: [
                  {
                    $in: [
                      "$$item.id",
                      [
                        11,
                        12
                      ]
                    ]
                  },
                  {
                    $eq: [
                      "$$item.name",
                      11
                    ]
                  }
                ]
              },
              {
                $and: [
                  {
                    $in: [
                      "$$item.id",
                      [
                        61,
                        62
                      ]
                    ]
                  },
                  {
                    $eq: [
                      "$$item.name",
                      12
                    ]
                  }
                ]
              }
            ]
          }
        }
      }
    }
  },
  {
    $project: {
      id: 1,
      name: 1,
      list: {
        $map: {
          input: "$list",
          as: "item1",
          in: {
            id: "$$item1.id",
            name: "$$item1.name",
            list: {
              $filter: {
                input: "$$item1.list",
                as: "item2",
                cond: {
                  $eq: [
                    "$$item2.name",
                    111
                  ]
                }
              }
            }
          }
        },
        
      }
    }
  }
])

db.collection.aggregate([
  {
    "$addFields": {
      "list": {
        "$map": {
          "input": "$list",
          "as": "a1",
          "in": {
            id: "$$a1.id",
            name: "$$a1.name",
            list: {
              "$map": {
                "input": "$$a1.list",
                "as": "a2",
                "in": {
                  id: "$$a2.id",
                  name: "$$a2.name",
                  list: {
                    "$filter": {
                      "input": "$$a2.list",
                      "as": "a3",
                      "cond": {
                        $eq: [
                          "$$a3.name",
                          1111
                        ]
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  
])

这两种代码都能得到正确的结果。

因为我的数组嵌套层次会很深,有没有其他更好的选择?


0
投票

如果你想保留原始数据,你应该在使用

replica
之前
field
$unwind
。找到数据后,删除
replica

db.runoob.aggregate([
  {
    $addFields: {
      newlist: "$list"
    }
  },
  {
    $unwind: "$newlist"
  },
  {
    $unwind: "$newlist.list"
  },
  {
    "$match": {
      "newlist.list.id": {
        "$in": [
          111
        ]
      }
    }
  },
  {
    "$unset": "newlist"
  }
])

MONGO 游乐场

操作

$match
也可以像下面这样:

{
    "$match": {
      "newlist.list.id": 111
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.