Search code examples
mongodbmongooseaggregation-frameworkwindow-functions

Grouping MongoDB Data by Ignition Field Values: A Solution for Large Datasets


I want to group the data based on the values of the "ignition" field. If the "ignition" value is 1, all records with the value 1 should be grouped together until the next value of 0 is encountered, and so on.

I have 86400 records in MongoDB, and I want to query the data to achieve the desired output.

The data looks like this:

[
  {
    ignition: 1,
    time: 112        
  },
  {
    ignition: 1,
    time: 193        
  },     
  {
    ignition: 0,
    time: 115        
  },
  {
    ignition: 1,
    time: 116        
  },
  {
    ignition: 1,
    time: 117        
  },
  {
    ignition: 1,
    time: 118        
  },
  {
    ignition: 0,
    time: 119        
  },
  {
    ignition: 1,
    time: 120        
  },
  {
    ignition: 1,
    time: 121        
  },
  {
    ignition: 1,
    time: 122        
  },
  {
    ignition: 0,
    time: 123        
  },
]

I want the output like this:

{
  time: [112,193],
  time: [116,117,118],
  time: [120,121,122]
}

Solution

  • db.collection.aggregate([
      {
        $setWindowFields: {                         //6. the output of this stage is, each set of adjacent documents having same $ignition will have a unique groupNum
          partitionBy: null,
          sortBy: {time: 1},                        //4. from all documents sorted by $time
          output: {
            "groupNum": {                           //1. create a new field groupNum
              $sum: {                               //2. by cumulatively adding
                $cond: [  
                  {$eq: ["$ignition",1]}, 0, 1      //3. modified $ignition field
                ]
              },
              window: {
                documents: ["unbounded","current"]  //5. starting from the beginning to current document
              }
            }
          }
        }
      },
      {
        $match: {"ignition": 1}                     //7. retain $ignition : 1
      },
      {
        $group: {
          _id: "$groupNum",                         //8. group by groupNum
          time: {$push: "$time"}                    //9. pushing the time to an array
        }
      },
      {
        $sort: {_id: 1}                             //10.sort as necessary
      }
    ])
    

    Demo