MongoDB Project Array Document Size with Condition

微笑、不失礼 提交于 2021-02-05 08:36:05

问题


Let's say I have the following document structure:

{
  "_id": "ID",
  "array": [
    {
      "a": "A",
      "b": "B",
      "c": {
        "x": true,
        "y": true,
        "z": false
      }
    },
    {
      "a": "A",
      "b": "B"
    },
    {
      "a": "A",
      "b": "B"
      "c": {
        "s": true
      }
    }
  ]
}

I am trying to do an aggregation which gives me this type of output:

{
  "_id": "ID",
  "array": [
    {
      "a": "A",
      "b": "B",
      "c": 2
    },
    {
      "a": "A",
      "b": "B",
      "c": 0
    },
    {
      "a": "A",
      "b": "B"
      "c": 1
    }
  ]
}

So what I want to do is to, instead of the document c, return the number of elements with true as value. And as in the example, the c field does not necessarily exist (in which case I want to return 0), and when it does, it's subfields are not necessarily the same as other c subfields in the array. Let's say I am doing the aggregation:

db.collection.aggregate([
  {"$match": {<conditions>}},
  {"$project": {
    "array.a": 1,
    "array.b": 1,
    "array.c": <?>,
  }}
])

How can I adjust "array.c" in the projection to accomplish what I'm after?


回答1:


You need to have at least MongoDB v3.4.4

Projecting "array.a": 1 will return ["A", "A", "A"]. Since your array field is an array, we need to use $map operator for iteration.

To iterate over object keys, we need to transform it into array with $objectToArray operator.

"c": {                   "c": [
    "x": true,             {k: "x", v: true},
    "y": true,       ->    {k: "y", v: true},
    "z": false             {k: "z", v: false},
  }                      ]

Then, we apply $filter operator to get just the k:v pairs whose v is true.


db.collection.aggregate([
  {
    $match: {}
  },
  {
    $project: {
      array: {
        $map: {
          input: "$array",
          as: "arr",
          in: {
            a: "$$arr.a",
            b: "$$arr.b",
            c: {
              $size: {
                $filter: {
                  input: {
                    $objectToArray: {
                      $ifNull: [
                        "$$arr.c",
                        {}
                      ]
                    }
                  },
                  cond: {
                    $eq: [
                      "$$this.v",
                      true
                    ]
                  }
                }
              }
            }
          }
        }
      }
    }
  }
])

MongoPlayground



来源:https://stackoverflow.com/questions/60952230/mongodb-project-array-document-size-with-condition

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!