Запрос MongoDB для фильтрации вложенных документов из вложенных массивов - PullRequest
1 голос
/ 05 марта 2020

Учитывая эту встроенную структуру документа:

organisation
  district
    property
      installation 
        installation_type

I wi sh, чтобы получить только свойства, где тип_установки = например, 'Газовый котел'

Я пробовал:

db.organisation.find({ "district.property.installation.installation_type": { $all: ['Gas boiler'] }})

, но при этом возвращается весь документ для любой организации с газовым котлом. Это означает, что я также получаю свойства, которые не имеют газовых котлов. Я хочу список только свойства с «Газовыми котлами»

Пример do c:

db.organisation.insert({
  _id: 'Organsiation 1',
  district: [
  {
    _id: 'District 1',
    property: [
      {
        _id: 'Property 1',
        address_line_1: 'Adress 1',
        installation: [
          {
            _id: 'HS01',
            installation_type: 'Gas boiler',
            component: [
              {
                _id: 'P01',
                component_type: 'Circulation pump',
              },
              {
                _id: 'EXP01',
                component_type: 'Expansion tank',
              },
            ],
          },
          {
            _id: 'HW01',
            installation_type: 'Electric water heater',
            component: [
              {
                _id: 'P01',
                component_type: 'Circulation pump',
              },
            ],
          },
          {
            _id: 'V01',
            installation_type: 'Ventilation',
          }
        ]
      },
    ]
  },
  {
    _id: 'District 2',
    property: [
      {
        _id: 'Property 2',
        address_line_1: 'Adress 2',
        installation: [
          {
            _id: 'HS01',
            installation_type: 'Geo Heat Pump',
          },
          {
            _id: 'HS02',
            installation_type: 'Gas boiler',
          }
        ]
      },
      {
        _id: 'Property 3',
        installation: [
          {
            _id: 'HS01',
            installation_type: 'Gas boiler',
          } 
        ]
      },
    ],
  }
]
})

Как мне это сделать

1 Ответ

1 голос
/ 05 марта 2020

С этим множеством вложенных массивов, вы либо делаете $unwind, либо используете фильтры, как показано ниже, но использование $unwind взорвет коллекцию с большими документами no.of, поэтому это должно работать так, как должно работать $addFields на Размер до c меньше исходного размера коллекции:

db.collection.aggregate([
    /** This match can be optional if dealing with data set of small size, else it can help a lot to filter docs which has at-least 'Gas boiler' */
    {
      $match: {
        "district.property.installation.installation_type": "Gas boiler"
      }
    },
    /** Iterate over each array till property array but on installation use filter to filter only object matches with required criteria,
     *  Use mergeObjects to merge actual object with returned array, to preserve other fields apart from `property` & `installation` */
    {
      $addFields: {
        district: {
          $map: {
            input: "$district",
            as: "d",
            in: {
              $mergeObjects: [
                "$$d",
                {
                  property: {
                    $map: {
                      input: "$$d.property",
                      as: "p",
                      in: {
                        $mergeObjects: [
                          "$$p",
                          {
                            installation: {
                              $filter: {
                                input: "$$p.installation",
                                cond: {
                                  $eq: [
                                    "$$this.installation_type",
                                    "Gas boiler"
                                  ]
                                }
                              }
                            }
                          }
                        ]
                      }
                    }
                  }
                }
              ]
            }
          }
        }
      }
    }
  ])

Тест: MongoDB-Playground

...