Home > Net >  Lodash `countBy` equivalent in MongoDB?
Lodash `countBy` equivalent in MongoDB?

Time:03-08

Let's say I have the input docs below:

[
  {
    "_id": "6225ca4052e7c226e2dd836d",
    "data": [
      "07",
      "07",
      "12",
      "19",
      "07",
      "32"
    ]
  },
  {
    "_id": "6225ca4052e7c226e2dd888f",
    "data": [
      "99",
      "97",
      "52",
      "99",
      "58",
      "92"
    ]
  }
]

I want to count the occurrences of every element in data string array per document. In JS, I can use countBy. How can I achieve the same using MongoDB Aggregation Framework?

I have tried to $reduce but MongoDB seems to not support assigning dynamic field to object.

{
  $reduce: {
    input: '$data',
    initialValue: {},
    in: { // assign `$$this` with count to `$$value`, but failed! }
  }
}

Below is the desired output.

[
  {
    "_id": "6225ca4052e7c226e2dd836d",
    "freqs": {
      "12": 1,
      "19": 1,
      "32": 1,
      "07": 3
    }
  },
  {
    "_id": "6225ca4052e7c226e2dd888f",
    "freqs": {
      "52": 1,
      "58": 1,
      "92": 1,
      "97": 1,
      "99": 2
    }
  }
]

CodePudding user response:

db.collection.aggregate([
  {
    $match: {}
  },
  {
    $unwind: "$data"
  },
  {
    $group: {
      _id: "$data",
      c: { $sum: 1 },
      id: { $first: "$_id" }
    }
  },
  {
    $group: {
      _id: "$id",
      data: { $push: { k: "$_id", v: "$c" } }
    }
  },
  {
    $set: {
      data: { $arrayToObject: "$data" }
    }
  }
])

mongoplayground


db.collection.aggregate([
  {
    $set: {
      data: {
        $function: {
          body: "function(d) {let obj = {}; d.forEach(e => {if(obj[e]==null) { obj[e]=1; }else{ obj[e]  ; }}); return obj;}",
          args: [
            "$data"
          ],
          lang: "js"
        }
      }
    }
  }
])

mongoplayground

  • Related