Mongodb фильтрует массив на основе другого элемента массива - PullRequest
1 голос
/ 29 января 2020

Допустим, у меня есть документ, как показано ниже

{
"_id" : 1,
"Quality" : [ 
        "HIGH", 
        "LOW", 
        "LOW", 
        "HIGH"
    ],
    "Pages" : [ 
        10, 
        10, 
        12, 
        17
    ]
}

Мне нужен результат как

{
"_id" : 1,
"HIGH" : 27
"LOW" : 22
}

Мне нужно создать два атрибута HIGH и LOW в соответствии с качеством путем суммирования их соответствующего индекса значения позиций массива Pages.

Я хотя и использовал $ filter и $ arrayElemAt , но мне не удалось получить позицию индекса при фильтрации по атрибуту Pages

high : { $sum:{ $filter: { input: "$Pages", as: "noOfPages", cond: {"$eq":[{ $arrayElemAt: ["$Quality", **Need to pass index position of $pages while filtering**]}, "HIGH"]}}}}

Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 29 января 2020

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

db.collection.aggregate([
  { "$project": {
    "Quality": {
      "$map": {
        "input": { "$range": [0, { "$size": "$Quality" }] },
        "in": {
          "Quality": { "$arrayElemAt": ["$Quality", "$$this"] },
          "Pages": { "$arrayElemAt": ["$Pages", "$$this"] }
        }
      }
    }
  }},
  { "$project": {
    "newArrayField": {
      "$map": {
        "input": { "$setUnion": ["$Quality.Quality"] },
        "as": "m",
        "in": {
          "k": "$$m",
          "v": {
            "$filter": {
              "input": "$Quality",
              "as": "d",
              "cond": {
                "$eq": ["$$d.Quality", "$$m"]
              }
            }
          }
        }
      }
    }
  }},
  { "$project": {
    "d": {
      "$arrayToObject": {
        "$map": {
          "input": "$newArrayField",
          "in": {
            "k": "$$this.k",
            "v": { "$sum": "$$this.v.Pages" }
          }
        }
      }
    }
  }}
])

MongoPlayground

0 голосов
/ 29 января 2020

Этого можно добиться с помощью 2 этапов агрегирования.

Первый - сопоставить 2 массива в один массив.

Второй - фильтрация одного массива с включением только HIGH (/ LOW), и сокращение отфильтрованного массива до единого элемента суммы.

[{$project: {
  "Quality": {
    $map: {
      input: {$range: [0, {$size: "$Quality"}]},
      as: "idx",
      in: {
        "Quality": { $arrayElemAt: ["$Quality", "$$idx"] },
        "Pages": { $arrayElemAt: ["$Pages", "$$idx"] }
      }
    }
  }
}}, {$project: {
  "HIGH": {
    $reduce: {
      input: {
        $filter: {
          input: "$Quality",
          as: "x",
          cond: {$eq: ["$$x.Quality", "HIGH"]}
        }
      },
      initialValue: 0,
      in: {
        $add: ["$$value", "$$this.Pages"]
      }
    }
  },
  "LOW": {
    $reduce: {
      input: {
        $filter: {
          input: "$Quality",
          as: "x",
          cond: {$eq: ["$$x.Quality", "LOW"]}
        }
      },
      initialValue: 0,
      in: {
        $add: ["$$value", "$$this.Pages"]
      }
    }
  }
}}]

Что дает именно то, что вы просили:

{
  _id: 1
  HIGH:27
  LOW:22
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...