Aggregation Pipeline example for datalogger (TimeSeries)

General

When collecting timeseries data, it’s stored in one document for each sensor and hour, containg readings for each minute interval.
This is an example of the document format is used:

{
	"_id":"5b735f61d9b51d0d5d55ded0",
	"sensor":24,
	"type":"bme280v1",
	"datetime":"2018-08-14T23:00:00.000Z",
	"readings":{
		"1":{"temperature":"11.59","humidity":"81.98","dewpoint":"8.6","pressure":"1009.79","rssi":"-90","battery":"2.907"},
		"4":{"temperature":"11.56","humidity":"81.97","dewpoint":"8.6","pressure":"1009.87","rssi":"-90","battery":"2.922"},
		"5":{"temperature":"11.55","humidity":"82.06","dewpoint":"8.6","pressure":"1009.91","rssi":"-92","battery":"2.922"},
		"6":{"temperature":"11.53","humidity":"82.17","dewpoint":"8.6","pressure":"1009.87","rssi":"-90","battery":"2.922"},
		"7":{"temperature":"11.51","humidity":"82.32","dewpoint":"8.6","pressure":"1009.87","rssi":"-91","battery":"2.922"},
		"8":{"temperature":"11.51","humidity":"82.46","dewpoint":"8.6","pressure":"1009.86","rssi":"-91","battery":"2.922"},
		"9":{"temperature":"11.49","humidity":"82.50","dewpoint":"8.6","pressure":"1009.86","rssi":"-90","battery":"2.922"},
		"10":{"temperature":"11.46","humidity":"82.56","dewpoint":"8.6","pressure":"1009.84","rssi":"-91","battery":"2.922"},
		"11":{"temperature":"11.46","humidity":"82.26","dewpoint":"8.5","pressure":"1009.94","rssi":"-90","battery":"2.922"},
		"12":{"temperature":"11.43","humidity":"82.30","dewpoint":"8.5","pressure":"1009.87","rssi":"-91","battery":"2.922"},
		"13":{"temperature":"11.43","humidity":"82.44","dewpoint":"8.5","pressure":"1009.99","rssi":"-93","battery":"2.922"},
		"14":{"temperature":"11.42","humidity":"82.47","dewpoint":"8.5","pressure":"1009.88","rssi":"-92","battery":"2.922"},
		"16":{"temperature":"11.39","humidity":"82.34","dewpoint":"8.5","pressure":"1009.85","rssi":"-91","battery":"2.922"},
		"17":{"temperature":"11.38","humidity":"82.33","dewpoint":"8.5","pressure":"1009.84","rssi":"-92","battery":"2.922"},
		"21":{"temperature":"11.33","humidity":"82.50","dewpoint":"8.5","pressure":"1009.83","rssi":"-92","battery":"2.922"},
		"22":{"temperature":"11.31","humidity":"82.50","dewpoint":"8.4","pressure":"1009.84","rssi":"-91","battery":"2.922"},
		"23":{"temperature":"11.30","humidity":"82.42","dewpoint":"8.4","pressure":"1009.88","rssi":"-92","battery":"2.922"},
		"24":{"temperature":"11.28","humidity":"82.35","dewpoint":"8.4","pressure":"1009.90","rssi":"-91","battery":"2.907"},
		"25":{"temperature":"11.26","humidity":"82.33","dewpoint":"8.4","pressure":"1009.81","rssi":"-91","battery":"2.922"},
		"26":{"temperature":"11.24","humidity":"82.52","dewpoint":"8.4","pressure":"1009.84","rssi":"-90","battery":"2.907"},
		"27":{"temperature":"11.24","humidity":"82.68","dewpoint":"8.4","pressure":"1009.88","rssi":"-91","battery":"2.907"},
		"29":{"temperature":"11.22","humidity":"82.73","dewpoint":"8.4","pressure":"1009.82","rssi":"-91","battery":"2.907"},
		"30":{"temperature":"11.20","humidity":"82.57","dewpoint":"8.3","pressure":"1009.80","rssi":"-90","battery":"2.907"},
		"31":{"temperature":"11.19","humidity":"82.74","dewpoint":"8.4","pressure":"1009.85","rssi":"-91","battery":"2.922"},
		"32":{"temperature":"11.19","humidity":"82.98","dewpoint":"8.4","pressure":"1009.82","rssi":"-91","battery":"2.907"},
		"33":{"temperature":"11.17","humidity":"82.99","dewpoint":"8.4","pressure":"1009.82","rssi":"-90","battery":"2.907"},
		"34":{"temperature":"11.15","humidity":"83.05","dewpoint":"8.4","pressure":"1009.78","rssi":"-90","battery":"2.907"},
		"35":{"temperature":"11.14","humidity":"82.77","dewpoint":"8.3","pressure":"1009.80","rssi":"-89","battery":"2.907"},
		"36":{"temperature":"11.11","humidity":"82.95","dewpoint":"8.3","pressure":"1009.78","rssi":"-91","battery":"2.922"},
		"40":{"temperature":"11.05","humidity":"82.85","dewpoint":"8.3","pressure":"1009.78","rssi":"-92","battery":"2.907"},
		"42":{"temperature":"11.02","humidity":"82.77","dewpoint":"8.2","pressure":"1009.77","rssi":"-91","battery":"2.907"},
		"43":{"temperature":"11.01","humidity":"82.60","dewpoint":"8.2","pressure":"1009.85","rssi":"-92","battery":"2.922"},
		"44":{"temperature":"11.01","humidity":"82.82","dewpoint":"8.2","pressure":"1009.85","rssi":"-92","battery":"2.878"},
		"45":{"temperature":"10.99","humidity":"82.58","dewpoint":"8.1","pressure":"1009.79","rssi":"-92","battery":"2.878"},
		"46":{"temperature":"10.96","humidity":"82.57","dewpoint":"8.1","pressure":"1009.88","rssi":"-90","battery":"2.878"},
		"47":{"temperature":"10.94","humidity":"82.75","dewpoint":"8.1","pressure":"1009.84","rssi":"-92","battery":"2.878"},
		"48":{"temperature":"10.93","humidity":"82.85","dewpoint":"8.1","pressure":"1009.88","rssi":"-91","battery":"2.907"},
		"49":{"temperature":"10.91","humidity":"82.70","dewpoint":"8.1","pressure":"1009.86","rssi":"-90","battery":"2.922"},
		"50":{"temperature":"10.89","humidity":"82.62","dewpoint":"8.1","pressure":"1009.83","rssi":"-90","battery":"2.878"},
		"51":{"temperature":"10.87","humidity":"82.56","dewpoint":"8.0","pressure":"1009.83","rssi":"-94","battery":"2.878"},
		"52":{"temperature":"10.85","humidity":"82.60","dewpoint":"8.0","pressure":"1009.87","rssi":"-90","battery":"2.907"},
		"53":{"temperature":"10.84","humidity":"82.88","dewpoint":"8.1","pressure":"1009.82","rssi":"-93","battery":"2.878"},
		"55":{"temperature":"10.81","humidity":"82.83","dewpoint":"8.0","pressure":"1009.83","rssi":"-90","battery":"2.907"},
		"56":{"temperature":"10.79","humidity":"83.31","dewpoint":"8.1","pressure":"1009.88","rssi":"-90","battery":"2.907"},
		"58":{"temperature":"10.77","humidity":"83.27","dewpoint":"8.1","pressure":"1009.86","rssi":"-90","battery":"2.907"},
		"59":{"temperature":"10.76","humidity":"83.13","dewpoint":"8.0","pressure":"1009.80","rssi":"-91","battery":"2.907"}
	}
}

To avoid lots of parsing during presentation for the data in for example Grafana aggregation pipeline can be used.

Aggregate the data for easier presentation

The goal is to transform this data into smaller documents containg only timestamp, sensorid and measurements.

[
  { 
    $match: {  
      sensor:24, 
      datetime: {$gte: ISODate('2018-08-14 20:00:00')}
    } 
  },
  { 
    $project: {
      sensor:1,
      datetime: 1,
      values:{$objectToArray: "$readings"}
    } 
  },
  { 
    $unwind: {  path: "$values"  } 
  }, 
  {
    $project: {
      _id:0,
      sensor:1,
      timestamp : {$add: ["$datetime", {$multiply: [60000, {$toInt: "$values.k"}]}]},
      data : "$values.v"
    }
  }
]

Resulting documents:

{
	sensor:24
	timestamp:2018-08-15 01:01:00.000
	data: {
		temperature:"11.59"
		humidity:"81.98"
		dewpoint:"8.6"
		pressure:"1009.79"
		rssi:"-90"
		battery:"2.907"
	}
}

{
	sensor:24
	timestamp:2018-08-15 01:04:00.000
	data: {
		temperature:"11.56"
		humidity:"81.97"
		dewpoint:"8.6"
		pressure:"1009.87"
		rssi:"-90"
		battery:"2.922"
	}
}
...

 

Don't be such an angerball