initprism
initprism

Reputation: 33

Aggregate multiple documents and count sum field

Document:

{
  _id: "___"
  finish: false or true
  ... some field..
}

Aggregate result:

{
  finish: 10,
  non_finish: 3,
  results: [
   docuemnt,
   docuemnt,
   ...
  ]
}

Is it possible? I know how can I count finish, with condition but how to aggregate document array?

Upvotes: 0

Views: 476

Answers (1)

Yong Shun
Yong Shun

Reputation: 51195

Solution 1

  1. $set - Set finish_count and non_finish_count fields by checking the finish, if match then 1, else 0.

  2. $group - Group by null, sum the finish_count and non_finish_count fields. Add each document into documents array.

  3. $unset - Remove documents.finish_count and documents.non_finish_countfields.

db.collection.aggregate([
  {
    $set: {
      finish_count: {
        $cond: {
          if: {
            $eq: [
              "$finish",
              true
            ]
          },
          then: 1,
          else: 0
        }
      },
      non_finish_count: {
        $cond: {
          if: {
            $eq: [
              "$finish",
              false
            ]
          },
          then: 1,
          else: 0
        }
      }
    }
  },
  {
    $group: {
      _id: null,
      finish: {
        $sum: "$finish_count"
      },
      non_finish: {
        $sum: "$non_finish_count"
      },
      documents: {
        $push: "$$ROOT"
      }
    }
  },
  {
    $unset: [
      "documents.finish_count",
      "documents.non_finish_count"
    ]
  }
])

Sample Mongo Playground (Solution 1)


Solution 2

  1. $group - Group by null, and add each document into the documents array.

  2. $set - Set the fields by counting the size ($size) of the array by filtering the document with finish (finish: true) and non_finish (finish: false) from the documents array.

db.collection.aggregate([
  {
    $group: {
      _id: null,
      documents: {
        $push: "$$ROOT"
      }
    }
  },
  {
    $set: {
      finish: {
        $size: {
          $filter: {
            input: "$documents",
            cond: {
              $eq: [
                "$$this.finish",
                true
              ]
            }
          }
        }
      },
      non_finish: {
        $size: {
          $filter: {
            input: "$documents",
            cond: {
              $eq: [
                "$$this.finish",
                false
              ]
            }
          }
        }
      }
    }
  }
])

Sample Mongo Playground (Solution 2)

Upvotes: 1

Related Questions