Итерация по двойному вложенному массиву в mongodb - PullRequest
0 голосов
/ 18 октября 2018

У меня есть следующий документ:

{
  "_ID": "234",
  "sub": {
    "abcId": "123",
    "subElems": [
      {
        "abcId": "345",
        "subElems": [
          {
            "abcId": "676",
            "subElems": [
              {
                "abcId": "567"
              },
              {
                "abcId": "567b",
                "crit1": false,
                "crit2": "someId",
                "crit3": "2013-07-30T22:00:00.000+0000",
                "crit4": "ABC"
              },
              {
                "abcId": "567c",
                "crit1": true,
                "crit3": "2013-07-30T22:00:00.000+0000",
                "crit4": "ABC"
              },
              {
                "abcId": "567d",
                "crit1": true,
                "crit3": "2018-11-30T22:00:00.000+0000",
                "crit4": "ABC"
              }
            ]
          },
                    {
            "abcId": "678",
            "subElems": [
              {
                "abcId": "568"
              },
              {
                "abcId": "568b",
                "crit1": false,
                "crit2": "someId",
                "crit3": "2013-07-30T22:00:00.000+0000",
                "crit4": "ABC"
              },
              {
                "abcId": "568c",
                "crit1": true,
                "crit3": "2013-07-30T22:00:00.000+0000",
                "crit4": "ABC"
              },
              {
                "abcId": "568d",
                "crit1": true,
                "crit3": "2018-11-30T22:00:00.000+0000",
                "crit4": "ABC"
              }
            ]
          }
        ]
      }
    ]
  }
}

Мне нужно перебрать все sub.subElems.0.subElems (в данном случае вложенные документы с abcId 676 и 678)

Каждый изэти 2 снова имеют массив объектов с именем subElems.

Мне нужно найти все объекты в этом массиве subElems, которые соответствуют следующим критериям (И, а не ИЛИ):

crit1 = true
crit4 = ABC
crit2 = null
crit3 = more than a year ago

Учитывая приведенный выше сборник, мне нужно:

567c и 568c

У меня есть различные агрегации.

Я думал, что мог бы сделать что-то вроде unwind sub.subElems.0.subElems, а затем получить доступ к массиву subElems и выполнить итерацию по нему.

Что я не знаю, как это сделать, - это выбрать вложенный массив объектов (путь которого я знаю), но затем выполнить итерацию по элементам вэтот массив и снова перебираем массив в этих объектах.

Спасибо за помощь и советы!

1 Ответ

0 голосов
/ 18 октября 2018

Вы можете попробовать ниже агрегации

В основном вам нужно использовать $map с каждым массивом и $filter с последним.

db.collection.aggregate([
  { "$addFields": {
    "sub.subElems": {
      "$map": {
        "input": "$sub.subElems",
        "as": "s1",
        "in": {
          "abcId": "$$s1.abcId",
          "subElems": {
            "$map": {
              "input": "$$s1.subElems",
              "as": "s2",
              "in": {
                "abcId": "$$s2.abcId",
                "subElems": {
                  "$filter": {
                    "input": "$$s2.subElems",
                    "as": "s3",
                    "cond": {
                      "$and": [
                        { "$eq": ["$$s3.crit1", true] },
                        { "$eq": ["$$s3.crit4", "ABC"] },
                        { "$eq": ["$$s3.crit2", undefined] },
                        { "$lt": ["$$s3.crit3", "2018-11-30T22:00:00.000+0000"] }
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }}
])
...