# Exploring Window Operators in Atlas Stream Processing

> Atlas Stream Processing is now available. Learn more about it here.

In our previous post on windowing, we introduced window operators available in Atlas Stream Processing. Window operators are one of the most commonly used operations to effectively process streaming data. Atlas Stream Processing provides two window operators: $tumblingWindow and $hoppingWindow. In this tutorial, we will explore both of these operators using the sample solar data generator provided within Atlas Stream Processing.

## Getting started

Before we begin creating stream processors, make sure you have a database user who has “atlasAdmin” access to the Atlas Project. Also, if you do not already have a Stream Processing Instance created with a connection to the sample_stream_solar data generator, please follow the instructions in Get Started with Atlas Stream Processing: Creating Your First Stream Processor and then continue on.

## View the solar stream sample data

For this tutorial, we will be using the MongoDB shell. 

First, confirm sample_stream_solar is added as a connection by issuing `sp.listConnections()`.

```
AtlasStreamProcessing> sp.listConnections()
{
    ok: 1,
    connections: 
     {
            name: 'sample_stream_solar',
            type: 'inmemory',
            createdAt: ISODate("2023-08-26T18:42:48.357Z")
        } 
    ]
}
```

Next, let’s define a **$source** stage to describe where Atlas Stream Processing will read the stream data from.

```
var solarstream={ $source: { "connectionName": "sample_stream_solar" } }
```

Then, issue a **.process** command to view the contents of the stream on the console.

```
sp.process([solarstream])
```

You will see the stream of solar data printed on the console. A sample of this data is as follows:

```json
{
    device_id: 'device_2',
    group_id: 3,
    timestamp: '2023-08-27T13:51:53.375+00:00',
    max_watts: 250,
    event_type: 0,
    obs: {
        watts: 168,
        temp: 15
    },
    _ts: ISODate("2023-08-27T13:51:53.375Z"),
    _stream_meta: {
        sourceType: 'sampleData',
        timestamp: ISODate("2023-08-27T13:51:53.375Z")
    }
}
```

## Create a tumbling window query

A tumbling window is a fixed-size window that moves forward in time at regular intervals. In Atlas Stream Processing, you use the [$tumblingWindow operator. In this example, let’s use the operator to compute the average watts over one-minute intervals.

Refer back to the schema from the sample stream solar data. To create a tumbling window, let’s create a variable and define our tumbling window stage. 

```javascript
var Twindow= { 
    $tumblingWindow: { 
         interval: { size: NumberInt(1), unit: "minute" },
         pipeline:  
             { 
                 $group: { 
                     _id: "$device_id", 
                    max: { $max: "$obs.watts" }, 
                    avg: { $avg: "$obs.watts" } 
                 }
             }
         ]
     } 
}
```

We are calculating the maximum value and average over the span of one-minute, non-overlapping intervals. Let’s use the `.process` command to run the streaming query in the foreground and view our results in the console.

```
sp.process([solarstream,Twindow])
```

Here is an example output of the statement:

```json
{
    _id: 'device_4',
    max: 236,
    avg: 95,
    _stream_meta: {
        sourceType: 'sampleData',
        windowStartTimestamp: ISODate("2023-08-27T13:59:00.000Z"),
        windowEndTimestamp: ISODate("2023-08-27T14:00:00.000Z")
    }
}
{
    _id: 'device_2',
    max: 211,
    avg: 117.25,
    _stream_meta: {
        sourceType: 'sampleData',
        windowStartTimestamp: ISODate("2023-08-27T13:59:00.000Z"),
        windowEndTimestamp: ISODate("2023-08-27T14:00:00.000Z")
    }
}
```

## Exploring the window operator pipeline

The pipeline that is used within a window function can include blocking stages and non-blocking stages.  

[Accumulator operators such as `$avg`, `$count`, `$sort`, and `$limit` can be used within blocking stages. Meaningful data returned from these operators are obtained when run over a series of data versus a single data point. This is why they are considered blocking. 

Non-blocking stages do not require multiple data points to be meaningful, and they include operators such as `$addFields`, `$match`, `$project`, `$set`, `$unset`, and `$unwind`, to name a few. You can use non-blocking before, after, or within the blocking stages. To illustrate this, let’s create a query that shows the average, maximum, and delta (the difference between the maximum and average). We will use a non-blocking **$match** to show only the results from device_1, calculate the tumblingWindow showing maximum and average, and then include another non-blocking `$addFields`. 

```
var m= { '$match': { device_id: 'device_1' } }
```

```javascript
var Twindow= {
    '$tumblingWindow': {
        interval: { size: Int32(1), unit: 'minute' },
        pipeline: 
            {
                '$group': {
                    _id: '$device_id',
                    max: { '$max': '$obs.watts' },
                    avg: { '$avg': '$obs.watts' }
                }
            }
        ]
    }
}

var delta = { '$addFields': { delta: { '$subtract': ['$max', '$avg'] } } }
```

Now we can use the .process command to run the stream processor in the foreground and view our results in the console.

```
sp.process([solarstream,m,Twindow,delta])
```

The results of this query will be similar to the following:

```json
{
    _id: 'device_1',
    max: 238,
    avg: 75.3,
    _stream_meta: {
        sourceType: 'sampleData',
        windowStartTimestamp: ISODate("2023-08-27T19:11:00.000Z"),
        windowEndTimestamp: ISODate("2023-08-27T19:12:00.000Z")
    },
    delta: 162.7
}
{
    _id: 'device_1',
    max: 220,
    avg: 125.08333333333333,
    _stream_meta: {
        sourceType: 'sampleData',
        windowStartTimestamp: ISODate("2023-08-27T19:12:00.000Z"),
        windowEndTimestamp: ISODate("2023-08-27T19:13:00.000Z")
    },
    delta: 94.91666666666667
}
{
    _id: 'device_1',
    max: 238,
    avg: 119.91666666666667,
    _stream_meta: {
        sourceType: 'sampleData',
        windowStartTimestamp: ISODate("2023-08-27T19:13:00.000Z"),
        windowEndTimestamp: ISODate("2023-08-27T19:14:00.000Z")
    },
    delta: 118.08333333333333
}
```

Notice the time segments and how they align on the minute. 

![Time segments aligned on the minute][1]

Additionally, notice that the output includes the difference between the calculated values of maximum and average for each window.

## Create a hopping window

A hopping window, sometimes referred to as a sliding window, is a fixed-size window that moves forward in time at overlapping intervals. In Atlas Stream Processing, you use the `$hoppingWindow` operator. In this example, let’s use the operator to see the average.

```javascript
var Hwindow = {
    '$hoppingWindow': {
        interval: { size: 1, unit: 'minute' },
        hopSize: { size: 30, unit: 'second' },
        pipeline: [
            {
                '$group': {
                    _id: '$device_id',
                    max: { '$max': '$obs.watts' },
                    avg: { '$avg': '$obs.watts' }
                }
            }
        ]
    }
}
```

To help illustrate the start and end time segments, let's create a filter to only return device_1.

```
var m = { '$match': { device_id: 'device_1' } }
```

Now let’s issue the `.process` command to view the results in the console.

```
sp.process([solarstream,m,Hwindow])
```

An example result is as follows:

```json
{
    _id: 'device_1',
    max: 238,
    avg: 76.625,
    _stream_meta: {
        sourceType: 'sampleData',
        windowStartTimestamp: ISODate("2023-08-27T19:37:30.000Z"),
        windowEndTimestamp: ISODate("2023-08-27T19:38:30.000Z")
    }
}
{
    _id: 'device_1',
    max: 238,
    avg: 82.71428571428571,
    _stream_meta: {
        sourceType: 'sampleData',
        windowStartTimestamp: ISODate("2023-08-27T19:38:00.000Z"),
        windowEndTimestamp: ISODate("2023-08-27T19:39:00.000Z")
    }
}
{
    _id: 'device_1',
    max: 220,
    avg: 105.54545454545455,
    _stream_meta: {
        sourceType: 'sampleData',
        windowStartTimestamp: ISODate("2023-08-27T19:38:30.000Z"),
        windowEndTimestamp: ISODate("2023-08-27T19:39:30.000Z")
    }
}
```

Notice the time segments.

![Overlapping time segments][2]

The time segments are overlapping by 30 seconds as was defined by the hopSize option. Hopping windows are useful to capture short-term patterns in data. 

## Summary

By continuously processing data within time windows, you can generate real-time insights and metrics, which can be crucial for applications like monitoring, fraud detection, and operational analytics. Atlas Stream Processing provides both tumbling and hopping window operators. Together these operators enable you to perform various aggregation operations such as sum, average, min, and max over a specific window of data. In this tutorial, you learned how to use both of these operators with solar sample data.  

### Learn more about MongoDB Atlas Stream Processing

Check out the [MongoDB Atlas Stream Processing announcement blog post. For more on window operators in Atlas Stream Processing, learn more in our documentation. 

>Log in today to get started. Atlas Stream Processing is available to all developers in Atlas. Give it a try today!

  [1]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/blt73ff54f0367cad3b/650da3ef69060a5678fc1242/image1.jpg
  [2]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/blt833bc1a824472d14/650da41aa5f15dea3afc5b55/image3.jpg