{"id":"timeseries","title":"Time series","url":"https:\/\/redis.io\/docs\/latest\/develop\/data-types\/timeseries\/","summary":"Ingest and query time series data with Redis","tags":["docs","develop","stack","oss","rs","rc","oss","kubernetes","clients"],"last_updated":"2026-05-04T15:45:09+02:00","children":[{"id":"configuration","summary":"Redis time series support multiple configuration parameters.","title":"Configuration Parameters","url":"https:\/\/redis.io\/docs\/latest\/develop\/data-types\/timeseries\/configuration\/"},{"id":"out-of-order_performance_considerations","summary":"Out-of-order \/ backfilled ingestion performance considerations","title":"Out-of-order \/ backfilled ingestion performance considerations","url":"https:\/\/redis.io\/docs\/latest\/develop\/data-types\/timeseries\/out-of-order_performance_considerations\/"},{"id":"use_cases","summary":"Time series use cases","title":"Use cases","url":"https:\/\/redis.io\/docs\/latest\/develop\/data-types\/timeseries\/use_cases\/"}],"page_type":"content","content_hash":"b3fbae835ee06d8585889759f74c1c0acd8f79159f8f46db70cf1e07c6dfe7e9","sections":[{"id":"time-series-command-summary","title":"Time series command summary","role":"content","text":"**17 commands in this group:**\n\n[View all timeseries commands](https:\/\/redis.io\/commands\/?group=timeseries)\n\n| Command | Summary | Complexity | Since |\n|---------|---------|------------|-------|\n| [TS.ADD](https:\/\/redis.io\/commands\/ts.add\/) | Append a sample to a time series | O(M) when M is the amount of compaction rules o... | 1.0.0 |\n| [TS.ALTER](https:\/\/redis.io\/commands\/ts.alter\/) | Update the retention, chunk size, duplicate policy, and labels of an existing time series | O(N) where N is the number of labels requested ... | 1.0.0 |\n| [TS.CREATE](https:\/\/redis.io\/commands\/ts.create\/) | Create a new time series | O(1) | 1.0.0 |\n| [TS.CREATERULE](https:\/\/redis.io\/commands\/ts.createrule\/) | Create a compaction rule | O(1) | 1.0.0 |\n| [TS.DECRBY](https:\/\/redis.io\/commands\/ts.decrby\/) | Decrease the value of the sample with the maximum existing timestamp, or create a new sample with a value equal to the value of the sample with the maximum existing timestamp with a given decrement | O(M) when M is the amount of compaction rules o... | 1.0.0 |\n| [TS.DEL](https:\/\/redis.io\/commands\/ts.del\/) | Delete all samples between two timestamps for a given time series | O(N) where N is the number of data points that ... | 1.6.0 |\n| [TS.DELETERULE](https:\/\/redis.io\/commands\/ts.deleterule\/) | Delete a compaction rule | O(1) | 1.0.0 |\n| [TS.GET](https:\/\/redis.io\/commands\/ts.get\/) | Get the sample with the highest timestamp from a given time series | O(1) | 1.0.0 |\n| [TS.INCRBY](https:\/\/redis.io\/commands\/ts.incrby\/) | Increase the value of the sample with the maximum existing timestamp, or create a new sample with a value equal to the value of the sample with the maximum existing timestamp with a given increment | O(M) when M is the amount of compaction rules o... | 1.0.0 |\n| [TS.INFO](https:\/\/redis.io\/commands\/ts.info\/) | Returns information and statistics for a time series | O(1) | 1.0.0 |\n\n#### Time series command summary (part 2)\n\n| Command | Summary | Complexity | Since |\n|---------|---------|------------|-------|\n| [TS.MADD](https:\/\/redis.io\/commands\/ts.madd\/) | Append new samples to one or more time series | O(N*M) when N is the amount of series updated a... | 1.0.0 |\n| [TS.MGET](https:\/\/redis.io\/commands\/ts.mget\/) | Get the sample with the highest timestamp from each time series matching a specific filter | O(n) where n is the number of time-series that ... | 1.0.0 |\n| [TS.MRANGE](https:\/\/redis.io\/commands\/ts.mrange\/) | Query a range across multiple time series by filters in forward direction | O(n\/m+k) where n = Number of data points, m = C... | 1.0.0 |\n| [TS.MREVRANGE](https:\/\/redis.io\/commands\/ts.mrevrange\/) | Query a range across multiple time-series by filters in reverse direction | O(n\/m+k) where n = Number of data points, m = C... | 1.4.0 |\n| [TS.QUERYINDEX](https:\/\/redis.io\/commands\/ts.queryindex\/) | Get all time series keys matching a filter list | O(n) where n is the number of time-series that ... | 1.0.0 |\n| [TS.RANGE](https:\/\/redis.io\/commands\/ts.range\/) | Query a range in forward direction | O(n\/m+k) where n = Number of data points, m = C... | 1.0.0 |\n| [TS.REVRANGE](https:\/\/redis.io\/commands\/ts.revrange\/) | Query a range in reverse direction | O(n\/m+k) where n = Number of data points, m = C... | 1.4.0 |\n\n\n\n[![Discord](https:\/\/img.shields.io\/discord\/697882427875393627?style=flat-square)](https:\/\/discord.gg\/KExRgMb)\n[![Github](https:\/\/img.shields.io\/static\/v1?label=&message=repository&color=5961FF&logo=github)](https:\/\/github.com\/RedisTimeSeries\/RedisTimeSeries\/)\n\nThe Redis time series data type lets you store real-valued data points\nalong with the time they were collected. You can combine the values from a selection\nof time series and query them by time or value range. You can also compute\naggregate functions of the data over periods of time and create new time series\nfrom the results. When you create a time series, you can specify a maximum\nretention period for the data, relative to the last reported timestamp, to\nprevent the time series from growing indefinitely.\n\nStarting from Redis 8.6, time series support NaN (Not a Number) values, which allow you to represent missing or invalid measurements while maintaining the temporal structure of your data.\n\nTime series support very fast reads and writes, making them ideal for\napplications such as:\n\n- Instrument data logging\n- System performance metrics\n- Financial market data\n- Internet of Things (IoT) sensor data\n- Smart metering\n- Quality of service (QoS) monitoring\n\nRedis time series are available in Redis Open Source, Redis Software, and Redis Cloud.\nSee\n[Install Redis Open Source](https:\/\/redis.io\/docs\/latest\/operate\/oss_and_stack\/install\/install-stack) or\n[Install Redis Software](https:\/\/redis.io\/docs\/latest\/operate\/rs\/installing-upgrading\/install)\nfor full installation instructions."},{"id":"create-a-time-series","title":"Create a time series","role":"content","text":"You can create a new empty time series with the [`TS.CREATE`](https:\/\/redis.io\/docs\/latest\/commands\/ts.create\/)\ncommand, specifying a key name. Alternatively, if you use [`TS.ADD`](https:\/\/redis.io\/docs\/latest\/commands\/ts.add\/)\nto add data to a time series key that does not exist, it is automatically created (see\n[Adding data points](#adding-data-points) below for more information about `TS.ADD`).\n\nFoundational: Use TS.CREATE to initialize a new time series key\n\n**Difficulty:** Beginner\n\n**Commands:** TS.CREATE, TYPE, TS.INFO\n\n**Complexity:**\n- TS.CREATE: O(1)\n- TYPE: O(1)\n- TS.INFO: O(1)\n\n**Available in:** Redis CLI, C#, Go, Java (Synchronous - Jedis), JavaScript (Node.js), Python\n\n##### Redis CLI\n\n[code example]\n\n##### C#\n\n[code example]\n\n##### Go\n\n[code example]\n\n##### Java (Synchronous - Jedis)\n\n[code example]\n\n##### JavaScript (Node.js)\n\n[code example]\n\n##### Python\n\n[code example]\n\n\n\nThe timestamp for each data point is a 64-bit integer value. The value\nrepresents a Unix timestamp, measured in milliseconds since the\n[Unix epoch](https:\/\/en.wikipedia.org\/wiki\/Unix_time).\nWhen you create a time series, you can specify a maximum retention period for the\ndata, relative to the last reported timestamp. A retention period of zero means\nthe data does not expire.\n\nData retention: Use TS.ADD with RETENTION option to automatically expire old data points based on time since the last update\n\n**Difficulty:** Intermediate\n\n**Builds upon:** create\n\n**Commands:** TS.ADD, TS.INFO\n\n**Complexity:**\n- TS.ADD: O(M)\n- TS.INFO: O(1)\n\n**Available in:** Redis CLI, C#, Go, Java (Synchronous - Jedis), JavaScript (Node.js), Python\n\n##### Redis CLI\n\n[code example]\n\n##### C#\n\n[code example]\n\n##### Go\n\n[code example]\n\n##### Java (Synchronous - Jedis)\n\n[code example]\n\n##### JavaScript (Node.js)\n\n[code example]\n\n##### Python\n\n[code example]\n\n\n\nYou can also add one or more *labels* to a time series when you create it. Labels\nare name-value pairs where both the name and value are strings. You can use\nthe names and values to select subsets of all the available time series\nfor queries and aggregations.\n\nLabeling: Add metadata labels to time series using LABELS option when you need to organize and filter series by attributes like location or sensor type\n\n**Difficulty:** Beginner\n\n**Builds upon:** create\n\n**Commands:** TS.ADD, TS.INFO\n\n**Complexity:**\n- TS.ADD: O(M)\n- TS.INFO: O(1)\n\n**Available in:** Redis CLI, C#, Go, Java (Synchronous - Jedis), JavaScript (Node.js), Python\n\n##### Redis CLI\n\n[code example]\n\n##### C#\n\n[code example]\n\n##### Go\n\n[code example]\n\n##### Java (Synchronous - Jedis)\n\n[code example]\n\n##### JavaScript (Node.js)\n\n[code example]\n\n##### Python\n\n[code example]"},{"id":"add-data-points","title":"Add data points","role":"content","text":"You can add individual data points with [`TS.ADD`](https:\/\/redis.io\/docs\/latest\/commands\/ts.add\/),\nbut you can also use [`TS.MADD`](https:\/\/redis.io\/docs\/latest\/commands\/ts.madd\/) to add multiple data\npoints to one or more time series in a single command. (Note that unlike `TS.ADD`, `TS.MADD`\ndoesn't create any new time series if you specify keys that don't exist.) The return value\nis an array containing the number of samples in each time series after the operation.\nIf you use the `*` character as the timestamp, Redis will record the current\nUnix time, as reported by the server's clock.\n\nBatch operations: Add multiple data points to one or more time series using TS.MADD when you need to reduce round trips to the server\n\n**Difficulty:** Beginner\n\n**Builds upon:** create\n\n**Commands:** TS.MADD\n\n**Complexity:**\n- TS.MADD: O(N*M)\n\n**Available in:** Redis CLI, C#, Go, Java (Synchronous - Jedis), JavaScript (Node.js), Python\n\n##### Redis CLI\n\n[code example]\n\n##### C#\n\n[code example]\n\n##### Go\n\n[code example]\n\n##### Java (Synchronous - Jedis)\n\n[code example]\n\n##### JavaScript (Node.js)\n\n[code example]\n\n##### Python\n\n[code example]"},{"id":"query-data-points","title":"Query data points","role":"content","text":"Use [`TS.GET`](https:\/\/redis.io\/docs\/latest\/commands\/ts.get\/) to retrieve the data point\nwith the highest timestamp in a time series. This returns both the timestamp and the value.\n\nFoundational: Use TS.GET to get the latest value and timestamp\n\n**Difficulty:** Beginner\n\n**Builds upon:** madd\n\n**Commands:** TS.GET\n\n**Complexity:**\n- TS.GET: O(1)\n\n**Available in:** Redis CLI, C#, Go, Java (Synchronous - Jedis), JavaScript (Node.js), Python\n\n##### Redis CLI\n\n[code example]\n\n##### C#\n\n[code example]\n\n##### Go\n\n[code example]\n\n##### Java (Synchronous - Jedis)\n\n[code example]\n\n##### JavaScript (Node.js)\n\n[code example]\n\n##### Python\n\n[code example]\n\n\n\nUse [`TS.RANGE`](https:\/\/redis.io\/docs\/latest\/commands\/ts.range\/) to retrieve data points\nfrom a time series that fall within a given timestamp range. The range is inclusive,\nmeaning that samples whose timestamp equals the start or end of the range are included.\nYou can use `-` and `+` as the start and end of the range, respectively, to\nindicate the minimum and maximum timestamps in the series. The response is\nan array of timestamp-value pairs returned in ascending order by timestamp.\nIf you want the results in descending order, use [`TS.REVRANGE`](https:\/\/redis.io\/docs\/latest\/commands\/ts.revrange\/) with the same parameters.\n\nRange queries: Retrieve data points within a timestamp range using TS.RANGE (ascending) or TS.REVRANGE (descending) when you need to analyze historical data\n\n**Difficulty:** Intermediate\n\n**Builds upon:** madd\n\n**Commands:** TS.CREATE, TS.MADD, TS.RANGE, TS.REVRANGE\n\n**Complexity:**\n- TS.CREATE: O(1)\n- TS.MADD: O(N*M)\n- TS.RANGE: O(n\/m+k)\n- TS.REVRANGE: O(n\/m+k)\n\n**Available in:** Redis CLI, C#, Go, Java (Synchronous - Jedis), JavaScript (Node.js), Python\n\n##### Redis CLI\n\n[code example]\n\n##### C#\n\n[code example]\n\n##### Go\n\n[code example]\n\n##### Java (Synchronous - Jedis)\n\n[code example]\n\n##### JavaScript (Node.js)\n\n[code example]\n\n##### Python\n\n[code example]\n\n\n\nBoth `TS.RANGE` and `TS.REVRANGE` also let you filter results. Specify\na list of timestamps to include only samples with those exact timestamps\nin the results (you must still specify timestamp range parameters if you\nuse this option). Specify a minimum and maximum value to include only\nsamples within that range. The value range is inclusive and you can\nuse the same value for the minimum and maximum to filter for a single value.\n\nFiltering results: Use FILTER_BY_TS and FILTER_BY_VALUE options with range queries when you need to select specific timestamps or value ranges\n\n**Difficulty:** Intermediate\n\n**Builds upon:** range\n\n**Commands:** TS.RANGE, TS.REVRANGE\n\n**Complexity:**\n- TS.RANGE: O(n\/m+k)\n- TS.REVRANGE: O(n\/m+k)\n\n**Available in:** Redis CLI, C#, Go, Java (Synchronous - Jedis), JavaScript (Node.js), Python\n\n##### Redis CLI\n\n[code example]\n\n##### C#\n\n[code example]\n\n##### Go\n\n[code example]\n\n##### Java (Synchronous - Jedis)\n\n[code example]\n\n##### JavaScript (Node.js)\n\n[code example]\n\n##### Python\n\n[code example]"},{"id":"query-multiple-time-series","title":"Query multiple time series","role":"content","text":"The `TS.GET`, `TS.RANGE`, and `TS.REVRANGE` commands also have\ncorresponding\n[`TS.MGET`](https:\/\/redis.io\/docs\/latest\/commands\/ts.mget\/),\n[`TS.MRANGE`](https:\/\/redis.io\/docs\/latest\/commands\/ts.mrange\/), and\n[`TS.MREVRANGE`](https:\/\/redis.io\/docs\/latest\/commands\/ts.mrevrange\/) versions that\noperate on multiple time series. `TS.MGET` returns the data point with the highest\ntimestamp from each time series, while `TS.MRANGE` and `TS.MREVRANGE`\nreturn data points from a range of timestamps in each time series.\n\nThe parameters are mostly the same except that the multiple time series\ncommands don't take a key name as the first parameter. Instead, you\nspecify a filter expression to include only time series with\nspecific labels. (See [Creating a time series](#creating-a-time-series)\nabove to learn how to add labels to a time series.) The filter expressions\nuse a simple syntax that lets you include or exclude time series based on\nthe presence or value of a label. See the description in the\n[`TS.MGET`](https:\/\/redis.io\/docs\/latest\/commands\/ts.mget#required-arguments) command reference\nfor details of the filter syntax. You can also request that\ndata points be returned with all their labels or with a selected subset of them.\n\nMulti-series queries: Use TS.MGET, TS.MRANGE, and TS.MREVRANGE with label filters when you need to query multiple time series based on label criteria\n\n**Difficulty:** Advanced\n\n**Builds upon:** create_labels\n\n**Commands:** TS.CREATE, TS.MADD, TS.MGET, TS.MRANGE, TS.MREVRANGE\n\n**Complexity:**\n- TS.CREATE: O(1)\n- TS.MADD: O(N*M)\n- TS.MGET: O(n)\n- TS.MRANGE: O(n\/m+k)\n- TS.MREVRANGE: O(n\/m+k)\n\n**Available in:** Redis CLI, C#, Go, Java (Synchronous - Jedis), JavaScript (Node.js), Python\n\n##### Redis CLI\n\n[code example]\n\n##### C#\n\n[code example]\n\n##### Go\n\n[code example]\n\n##### Java (Synchronous - Jedis)\n\n[code example]\n\n##### JavaScript (Node.js)\n\n[code example]\n\n##### Python\n\n[code example]"},{"id":"aggregation","title":"Aggregation","role":"content","text":"A time series can become large if samples are added very frequently. Instead\nof dealing with individual samples, it is sometimes useful to split the full\ntime range of the series into equal-sized \"buckets\" and represent each\nbucket by an aggregate value, such as the average or maximum value.\n\nFor example, if you expect to collect more than one billion data points in a day, you could aggregate the data using buckets of one minute. Since each bucket is represented by a single value, this reduces \nthe dataset size to 1,440 data points (24 hours x 60 minutes = 1,440 minutes).\n\nThe range query commands let you specify an aggregation function and bucket size.\nThe available aggregation functions are:\n\n- `avg`: Arithmetic mean of all values\n- `sum`: Sum of all values\n- `min`: Minimum value\n- `max`: Maximum value\n- `range`: Difference between the highest and the lowest value\n- `count`: Number of values\n- `countNaN`: Number of NaN values (since Redis 8.6)\n- `countAll`: Number of all values, both NaN and non-NaN (since Redis 8.6)\n- `first`: Value with lowest timestamp in the bucket\n- `last`:  Value with highest timestamp in the bucket\n- `std.p`: Population standard deviation of the values\n- `std.s`: Sample standard deviation of the values\n- `var.p`: Population variance of the values\n- `var.s`: Sample variance of the values\n- `twa`: Time-weighted average over the bucket's timeframe (since RedisTimeSeries v1.8)\n\nFor example, the example below shows an aggregation with the `avg` function over all\nfive data points in the `rg:2` time series. The bucket size is 2ms, so there are three\naggregated values with only one value used to calculate the average for the last bucket.\n\nAggregation: Use AGGREGATION option with range queries to compute statistics such as avg, sum, min, and max over time buckets when you need to reduce large datasets\n\n**Difficulty:** Intermediate\n\n**Builds upon:** madd\n\n**Commands:** TS.RANGE\n\n**Complexity:**\n- TS.RANGE: O(n\/m+k)\n\n**Available in:** Redis CLI, C#, Go, Java (Synchronous - Jedis), JavaScript (Node.js), Python\n\n##### Redis CLI\n\n[code example]\n\n##### C#\n\n[code example]\n\n##### Go\n\n[code example]\n\n##### Java (Synchronous - Jedis)\n\n[code example]\n\n##### JavaScript (Node.js)\n\n[code example]\n\n##### Python\n\n[code example]\n\n\n\n<note><b>NaN Handling (Redis 8.6+):<\/b> Starting from Redis 8.6, all existing aggregation functions ignore NaN values when computing results. For example, if a bucket contains values [1.0, NaN, 3.0], the `avg` aggregator will return 2.0 (average of 1.0 and 3.0), and the `count` aggregator will return 2. Use the new `countNaN` and `countAll` aggregators to count NaN values and total values respectively.<\/note>"},{"id":"bucket-alignment","title":"Bucket alignment","role":"content","text":"The sequence of buckets has a reference timestamp, which is the timestamp where\nthe first bucket in the sequence starts. By default, the reference timestamp is zero.\nFor example, the following commands create a time series and apply a `min` aggregation\nwith a bucket size of 25 milliseconds at the default zero alignment.\n\nBucket alignment: Use AGGREGATION with default zero alignment to group data into fixed-size time buckets when you need consistent time-based aggregations\n\n**Difficulty:** Intermediate\n\n**Builds upon:** agg\n\n**Commands:** TS.CREATE, TS.MADD, TS.RANGE\n\n**Complexity:**\n- TS.CREATE: O(1)\n- TS.MADD: O(N*M)\n- TS.RANGE: O(n\/m+k)\n\n**Available in:** Redis CLI, C#, Go, Java (Synchronous - Jedis), JavaScript (Node.js), Python\n\n##### Redis CLI\n\n[code example]\n\n##### C#\n\n[code example]\n\n##### Go\n\n[code example]\n\n##### Java (Synchronous - Jedis)\n\n[code example]\n\n##### JavaScript (Node.js)\n\n[code example]\n\n##### Python\n\n[code example]\n\n\n\nThe diagram below shows the aggregation buckets and their alignment to the reference timestamp\nat time zero.\n\n[code example]\n\nYou can also align the buckets to the start or end of the query range. For example, the following command aligns the buckets to the start of the query range at time 10.\n\nCustom alignment: Use ALIGN option with aggregations to align buckets to query range start\/end when you need aggregations relative to specific time boundaries\n\n**Difficulty:** Advanced\n\n**Builds upon:** agg_bucket\n\n**Commands:** TS.RANGE\n\n**Complexity:**\n- TS.RANGE: O(n\/m+k)\n\n**Available in:** Redis CLI, C#, Go, Java (Synchronous - Jedis), JavaScript (Node.js), Python\n\n##### Redis CLI\n\n[code example]\n\n##### C#\n\n[code example]\n\n##### Go\n\n[code example]\n\n##### Java (Synchronous - Jedis)\n\n[code example]\n\n##### JavaScript (Node.js)\n\n[code example]\n\n##### Python\n\n[code example]\n\n\n\nThe diagram below shows this arrangement of buckets.\n\n[code example]"},{"id":"aggregation-across-timeseries","title":"Aggregation across timeseries","role":"content","text":"By default, the results from\n[`TS.MRANGE`](https:\/\/redis.io\/docs\/latest\/commands\/ts.mrange\/) and\n[`TS.MREVRANGE`](https:\/\/redis.io\/docs\/latest\/commands\/ts.mrevrange\/) are grouped by time series. However, you can use the `GROUPBY` and `REDUCE` options to group them by label and apply an aggregation over elements\nthat have the same timestamp and the same label value (this feature is available from RedisTimeSeries v1.6 onwards).\n\nFor example, the following commands create four time series, two for the UK and two for the US, and add some data points. The first `TS.MRANGE` command groups the results by country and applies a `max` aggregation to find the maximum sample value in each country at each timestamp. The second `TS.MRANGE` command uses the same grouping, but applies an `avg` aggregation.\n\nCross-series aggregation: Use GROUPBY and REDUCE with TS.MRANGE to aggregate data across multiple time series by label when you need to compute statistics across groups\n\n**Difficulty:** Advanced\n\n**Builds upon:** agg, create_labels\n\n**Commands:** TS.CREATE, TS.MADD, TS.MRANGE\n\n**Complexity:**\n- TS.CREATE: O(1)\n- TS.MADD: O(N*M)\n- TS.MRANGE: O(n\/m+k)\n\n**Available in:** Redis CLI, C#, Go, Java (Synchronous - Jedis), JavaScript (Node.js), Python\n\n##### Redis CLI\n\n[code example]\n\n##### C#\n\n[code example]\n\n##### Go\n\n[code example]\n\n##### Java (Synchronous - Jedis)\n\n[code example]\n\n##### JavaScript (Node.js)\n\n[code example]\n\n##### Python\n\n[code example]"},{"id":"nan-values","title":"NaN Values","role":"content","text":"Starting from Redis 8.6, time series support NaN (Not a Number) values. This feature allows you to insert measurements that represent missing, invalid, or unknown data while preserving the temporal structure of your time series."},{"id":"use-cases-for-nan-values","title":"Use Cases for NaN Values","role":"content","text":"NaN values are useful in scenarios where you need to distinguish between:\n- **Missing data**: A timestamp where no measurement was taken\n- **Invalid data**: A timestamp where a measurement was attempted but failed (for example, sensor malfunction)\n- **Unknown data**: A timestamp where the measurement value is semantically \"unknown\" and may be filled in later"},{"id":"nan-behavior","title":"NaN Behavior","role":"content","text":"- **Adding NaN values**: Use [`TS.ADD`](https:\/\/redis.io\/docs\/latest\/commands\/ts.add\/) and [`TS.MADD`](https:\/\/redis.io\/docs\/latest\/commands\/ts.madd\/) to insert NaN values\n- **Querying NaN values**: All raw measurement queries ([`TS.GET`](https:\/\/redis.io\/docs\/latest\/commands\/ts.get\/), [`TS.RANGE`](https:\/\/redis.io\/docs\/latest\/commands\/ts.range\/), etc.) include NaN values in results\n- **Aggregation with NaN**: All existing aggregation functions except `countNaN` and `countAll` ignore NaN values. Use `countNaN` and `countAll` to count NaN and total values\n- **Increment\/Decrement**: [`TS.INCRBY`](https:\/\/redis.io\/docs\/latest\/commands\/ts.incrby\/) and [`TS.DECRBY`](https:\/\/redis.io\/docs\/latest\/commands\/ts.decrby\/) return errors when the current value or operand is NaN\n- **Duplicate policies**: Special handling for `MIN`, `MAX`, and `SUM` policies when mixing NaN and non-NaN values\n- **Filtering**: [`FILTER_BY_VALUE`](https:\/\/redis.io\/docs\/latest\/commands\/ts.range#filter_by_value-min-max-since-redistimeseries-v16) parameters cannot be NaN values\n- **Ignore duplicates**: NaN values are never considered duplicates when using `IGNORE` parameters\n\n[code example]"},{"id":"compaction","title":"Compaction","role":"content","text":"[Aggregation](#aggregation) queries let you extract the important information from a large data set\ninto a smaller, more manageable set. If you are continually adding new data to a\ntime series as it is generated, you may need to run the same aggregation\nregularly on the latest data. Instead of running the query manually\neach time, you can add a *compaction rule* to a time series to compute an\naggregation incrementally on data as it arrives. The values from the\naggregation buckets are stored in a separate time series, leaving the original\nseries unchanged.\n\nUse [`TS.CREATERULE`](https:\/\/redis.io\/docs\/latest\/commands\/ts.createrule\/) to create a\ncompaction rule, specifying the source and destination time series keys, the\naggregation function, and the bucket duration. Note that the destination time\nseries must already exist when you create the rule and also that the compaction will\nonly process data that is added to the source series after you create the rule.\n\nFor example, you could use the commands below to create a time series along with a\ncompaction rule to find the minimum reading in each period of 3ms.\n\nCompaction rules: Use TS.CREATERULE to automatically aggregate data into a destination time series when you need to maintain pre-computed aggregations\n\n**Difficulty:** Advanced\n\n**Builds upon:** create\n\n**Commands:** TS.CREATE, TS.CREATERULE, TS.INFO\n\n**Complexity:**\n- TS.CREATE: O(1)\n- TS.CREATERULE: O(1)\n- TS.INFO: O(1)\n\n**Available in:** Redis CLI, C#, Go, Java (Synchronous - Jedis), JavaScript (Node.js), Python\n\n##### Redis CLI\n\n[code example]\n\n##### C#\n\n[code example]\n\n##### Go\n\n[code example]\n\n##### Java (Synchronous - Jedis)\n\n[code example]\n\n##### JavaScript (Node.js)\n\n[code example]\n\n##### Python\n\n[code example]\n\n\n\nAdding data points within the first 3ms (the first bucket) doesn't\nproduce any data in the compacted series. However, when you add data for\ntime 4 (in the second bucket), the compaction rule computes the minimum\nvalue for the first bucket and adds it to the compacted series.\n\nCompaction behavior: Understand how compaction rules process data incrementally, computing aggregates for completed buckets when new data arrives\n\n**Difficulty:** Intermediate\n\n**Builds upon:** create_compaction\n\n**Commands:** TS.MADD, TS.RANGE, TS.ADD\n\n**Complexity:**\n- TS.MADD: O(N*M)\n- TS.RANGE: O(n\/m+k)\n- TS.ADD: O(M)\n\n**Available in:** Redis CLI, C#, Go, Java (Synchronous - Jedis), JavaScript (Node.js), Python\n\n##### Redis CLI\n\n[code example]\n\n##### C#\n\n[code example]\n\n##### Go\n\n[code example]\n\n##### Java (Synchronous - Jedis)\n\n[code example]\n\n##### JavaScript (Node.js)\n\n[code example]\n\n##### Python\n\n[code example]\n\n\n\nThe general strategy is that the rule does not add data to the\ncompaction for the latest bucket in the source series, but will add and\nupdate the compacted data for any previous buckets. This reflects the\ntypical usage pattern of adding data samples sequentially in real time\n(an aggregate value typically isn't correct until its bucket period is over).\nBut note that earlier buckets are not \"closed\" when you add data to a later\nbucket. If you add or [delete](#deleting-data-points) data in a bucket before\nthe latest one, the compaction rule will still update the compacted data for\nthat bucket."},{"id":"delete-data-points","title":"Delete data points","role":"content","text":"Use [`TS.DEL`](https:\/\/redis.io\/docs\/latest\/commands\/ts.del\/) to delete data points\nthat fall within a given timestamp range. The range is inclusive, meaning that\nsamples whose timestamp equals the start or end of the range are deleted.\nIf you want to delete a single timestamp, use it as both the start and end of the range.\n\nDeleting data: Use TS.DEL to remove data points within a timestamp range when you need to clean up or correct historical data\n\n**Difficulty:** Beginner\n\n**Builds upon:** create\n\n**Commands:** TS.INFO, TS.ADD, TS.DEL\n\n**Complexity:**\n- TS.INFO: O(1)\n- TS.ADD: O(M)\n- TS.DEL: O(N)\n\n**Available in:** Redis CLI, C#, Go, Java (Synchronous - Jedis), JavaScript (Node.js), Python\n\n##### Redis CLI\n\n[code example]\n\n##### C#\n\n[code example]\n\n##### Go\n\n[code example]\n\n##### Java (Synchronous - Jedis)\n\n[code example]\n\n##### JavaScript (Node.js)\n\n[code example]\n\n##### Python\n\n[code example]"},{"id":"use-time-series-with-other-metrics-tools","title":"Use time series with other metrics tools","role":"content","text":"In the [RedisTimeSeries](https:\/\/github.com\/RedisTimeSeries) GitHub organization, you can\nfind projects that help you integrate RedisTimeSeries with other tools, including:\n\n1. [Prometheus](https:\/\/github.com\/RedisTimeSeries\/prometheus-redistimeseries-adapter), a read\/write adapter to use RedisTimeSeries as the backend database.\n2. [Grafana 7.1+](https:\/\/github.com\/RedisTimeSeries\/grafana-redis-datasource), using the [Redis Data Source](https:\/\/redislabs.com\/blog\/introducing-the-redis-data-source-plug-in-for-grafana\/).\n3. [Telegraf](https:\/\/github.com\/influxdata\/telegraf). Download the plugin from [InfluxData](https:\/\/portal.influxdata.com\/downloads\/). \n4. StatsD, Graphite exports using graphite protocol."},{"id":"more-information","title":"More information","role":"content","text":"The other pages in this section describe RedisTimeSeries concepts in more detail.\nSee also the [time series command reference](https:\/\/redis.io\/docs\/latest\/commands\/?group=timeseries)."}],"examples":[{"id":"create-a-time-series-ex0","language":"plaintext","code":"> TS.CREATE thermometer:1\nOK\n> TYPE thermometer:1\nTSDB-TYPE\n> TS.INFO thermometer:1\n 1) totalSamples\n 2) (integer) 0\n    .\n    .","section_id":"create-a-time-series"},{"id":"create-a-time-series-ex1","language":"csharp","code":"bool res1 = db.TS().Create(\n            \"thermometer:1\",\n            new TsCreateParamsBuilder().build()\n        );\n        Console.WriteLine(res1); \/\/ >>> True\n\n        RedisType res2 = db.KeyType(\"thermometer:1\");\n        Console.WriteLine(res2); \/\/ >>> TSDB-TYPE\n\n        TimeSeriesInformation res3 = db.TS().Info(\"thermometer:1\");\n        Console.WriteLine(res3.TotalSamples); \/\/ >>> 0","section_id":"create-a-time-series"},{"id":"create-a-time-series-ex2","language":"go","code":"res1, err := rdb.TSCreate(ctx, \"thermometer:1\").Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res1) \/\/ >>> OK\n\n\tres2, err := rdb.Type(ctx, \"thermometer:1\").Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res2) \/\/ >>> TSDB-TYPE\n\n\tres3, err := rdb.TSInfo(ctx, \"thermometer:1\").Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res3[\"totalSamples\"]) \/\/ >>> 0","section_id":"create-a-time-series"},{"id":"create-a-time-series-ex3","language":"java","code":"String res1 = jedis.tsCreate(\"thermometer:1\");\n        System.out.println(res1); \/\/ >>> OK\n\n        String res2 = jedis.type(\"thermometer:1\");\n        System.out.println(res2); \/\/ >>> TSDB-TYPE\n\n        TSInfo res3 = jedis.tsInfo(\"thermometer:1\");\n        System.out.println(res3.getProperty(\"totalSamples\")); \/\/ >>> 0","section_id":"create-a-time-series"},{"id":"create-a-time-series-ex4","language":"javascript","code":"const res1 = await client.ts.create('thermometer:1');\nconsole.log(res1); \/\/ >>> OK\n\nconst res2 = await client.type('thermometer:1');\nconsole.log(res2); \/\/ >>> TSDB-TYPE\n\nconst res3 = await client.ts.info('thermometer:1');\nconsole.log(res3);\n\/\/ >>> { rules: [], ... totalSamples: 0, ...","section_id":"create-a-time-series"},{"id":"create-a-time-series-ex5","language":"python","code":"res1 = r.ts().create(\"thermometer:1\")\nprint(res1)  # >>> True\n\nres2 = r.type(\"thermometer:1\")\nprint(res2)  # >>> TSDB-TYPE\n\nres3 = r.ts().info(\"thermometer:1\")\nprint(res3)\n# >>> {'rules': [], ... 'total_samples': 0, ...","section_id":"create-a-time-series"},{"id":"create-a-time-series-ex6","language":"plaintext","code":"# Create a new time series with a first value of 10.8 (Celsius), recorded at time 1, with a retention period of 100ms.\n> TS.ADD thermometer:2 1 10.8 RETENTION 100\n(integer) 1\n> TS.INFO thermometer:2\n    .\n    .\n 9) retentionTime\n10) (integer) 100\n    .\n    .","section_id":"create-a-time-series"},{"id":"create-a-time-series-ex7","language":"csharp","code":"long res4 = db.TS().Add(\n            \"thermometer:2\",\n            new TsAddParamsBuilder()\n                .AddTimestamp(1)\n                .AddValue(10.8)\n                .AddRetentionTime(100)\n                .build()\n        );\n        Console.WriteLine(res4); \/\/ >>> 1\n\n        TimeSeriesInformation res5 = db.TS().Info(\"thermometer:2\");\n        Console.WriteLine(res5.RetentionTime);\n        \/\/ >>> 100","section_id":"create-a-time-series"},{"id":"create-a-time-series-ex8","language":"go","code":"res4, err := rdb.TSAddWithArgs(\n\t\tctx,\n\t\t\"thermometer:2\",\n\t\t1,\n\t\t10.8,\n\t\t&redis.TSOptions{\n\t\t\tRetention: 100,\n\t\t},\n\t).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res4) \/\/ >>> 1\n\n\tres5, err := rdb.TSInfo(ctx, \"thermometer:2\").Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res5[\"retentionTime\"]) \/\/ >>> 100","section_id":"create-a-time-series"},{"id":"create-a-time-series-ex9","language":"java","code":"long res4 = jedis.tsAdd(\"thermometer:2\", 1L, 10.8, \n            TSCreateParams.createParams().retention(100));\n        System.out.println(res4); \/\/ >>> 1\n\n        TSInfo res5 = jedis.tsInfo(\"thermometer:2\");\n        System.out.println(res5.getProperty(\"retentionTime\")); \/\/ >>> 100","section_id":"create-a-time-series"},{"id":"create-a-time-series-ex10","language":"javascript","code":"const res4 = await client.ts.add('thermometer:2', 1, 10.8, { RETENTION: 100 });\nconsole.log(res4); \/\/ >>> 1\n\nconst res5 = await client.ts.info('thermometer:2');\nconsole.log(res5);\n\/\/ >>> { rules: [], ... retentionTime: 100, ...","section_id":"create-a-time-series"},{"id":"create-a-time-series-ex11","language":"python","code":"res4 = r.ts().add(\"thermometer:2\", 1, 10.8, retention_msecs=100)\nprint(res4)  # >>> 1\n\nres5 = r.ts().info(\"thermometer:2\")\nprint(res5)\n# >>> {'rules': [], ... 'retention_msecs': 100, ...","section_id":"create-a-time-series"},{"id":"create-a-time-series-ex12","language":"plaintext","code":"> TS.ADD thermometer:3 1 10.4 LABELS location UK type Mercury\n(integer) 1\n> TS.INFO thermometer:3\n 1) totalSamples\n 2) (integer) 1\n 3) memoryUsage\n 4) (integer) 5000\n    .\n    .\n19) labels\n20) 1) 1) \"location\"\n       2) \"UK\"\n    2) 1) \"type\"\n       2) \"Mercury\"\n    .\n    .","section_id":"create-a-time-series"},{"id":"create-a-time-series-ex13","language":"csharp","code":"var labels = new List<TimeSeriesLabel>\n        {\n            new(\"location\", \"UK\"),\n            new(\"type\", \"Mercury\")\n        };\n        long res6 = db.TS().Add(\n            \"thermometer:3\",\n            new TsAddParamsBuilder()\n                .AddTimestamp(1)\n                .AddValue(10.4)\n                .AddLabels(labels)\n                .build()\n        );\n        Console.WriteLine(res6); \/\/ >>> 1\n\n        TimeSeriesInformation res7 = db.TS().Info(\"thermometer:3\");\n        Console.WriteLine(\n            $\"Labels: {string.Join(\", \", res7.Labels!.Select(l => $\"{l.Key}={l.Value}\"))}\"\n        );\n        \/\/ >>> Labels: location=UK, type=Mercury","section_id":"create-a-time-series"},{"id":"create-a-time-series-ex14","language":"go","code":"res6, err := rdb.TSAddWithArgs(\n\t\tctx,\n\t\t\"thermometer:3\",\n\t\t1,\n\t\t10.4,\n\t\t&redis.TSOptions{\n\t\t\tLabels: map[string]string{\n\t\t\t\t\"location\": \"UK\",\n\t\t\t\t\"type\":     \"Mercury\",\n\t\t\t},\n\t\t},\n\t).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res6) \/\/ >>> 1\n\n\tres7, err := rdb.TSInfo(ctx, \"thermometer:3\").Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res7[\"labels\"])\n\t\/\/ >>> map[location:UK type:Mercury]","section_id":"create-a-time-series"},{"id":"create-a-time-series-ex15","language":"java","code":"Map<String, String> labels = new HashMap<>();\n        labels.put(\"location\", \"UK\");\n        labels.put(\"type\", \"Mercury\");\n        \n        long res6 = jedis.tsAdd(\"thermometer:3\", 1L, 10.4,\n            TSCreateParams.createParams().labels(labels));\n        System.out.println(res6); \/\/ >>> 1\n\n        TSInfo res7 = jedis.tsInfo(\"thermometer:3\");\n        System.out.println(\"Labels: \" + res7.getLabels());\n        \/\/ >>> Labels: {location=UK, type=Mercury}","section_id":"create-a-time-series"},{"id":"create-a-time-series-ex16","language":"javascript","code":"const res6 = await client.ts.add('thermometer:3', 1, 10.4, {\n  LABELS: { location: 'UK', type: 'Mercury' }\n});\nconsole.log(res6); \/\/ >>> 1\n\nconst res7 = await client.ts.info('thermometer:3');\nconsole.log(res7);\n\/\/ >>> { labels: [{ name: 'location', value: 'UK' }, { name: 'type', value: 'Mercury' }], ... }","section_id":"create-a-time-series"},{"id":"create-a-time-series-ex17","language":"python","code":"res6 = r.ts().create(\n    \"thermometer:3\", 1, 10.4,\n    labels={\"location\": \"UK\", \"type\": \"Mercury\"}\n)\nprint(res6)  # >>> 1\n\nres7 = r.ts().info(\"thermometer:3\")\nprint(res7)\n# >>> {'rules': [], ... 'labels': {'location': 'UK', 'type': 'Mercury'}, ...","section_id":"create-a-time-series"},{"id":"add-data-points-ex0","language":"plaintext","code":"> TS.MADD thermometer:1 1 9.2 thermometer:1 2 9.9 thermometer:2 2 10.3\n1) (integer) 1\n2) (integer) 2\n3) (integer) 2","section_id":"add-data-points"},{"id":"add-data-points-ex1","language":"csharp","code":"var sequence = new List<(string, TimeStamp, double)>\n        {\n            (\"thermometer:1\", 1, 9.2),\n            (\"thermometer:1\", 2, 9.9),\n            (\"thermometer:2\", 2, 10.3)\n        };\n        IReadOnlyList<TimeStamp> res8 = db.TS().MAdd(sequence);\n        Console.WriteLine($\"[{string.Join(\", \", res8.Select(t => t.Value))}]\");\n        \/\/ >>> [1, 2, 2]","section_id":"add-data-points"},{"id":"add-data-points-ex2","language":"go","code":"res1, err := rdb.TSMAdd(ctx, [][]interface{}{\n\t\t{\"thermometer:1\", 1, 9.2},\n\t\t{\"thermometer:1\", 2, 9.9},\n\t\t{\"thermometer:2\", 2, 10.3},\n\t}).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res1) \/\/ >>> [1 2 2]","section_id":"add-data-points"},{"id":"add-data-points-ex3","language":"java","code":"List<Long> res8 = jedis.tsMAdd(\n            new AbstractMap.SimpleEntry<>(\"thermometer:1\", new TSElement(1L, 9.2)),\n            new AbstractMap.SimpleEntry<>(\"thermometer:1\", new TSElement(2L, 9.9)),\n            new AbstractMap.SimpleEntry<>(\"thermometer:2\", new TSElement(2L, 10.3))\n        );\n        System.out.println(res8); \/\/ >>> [1, 2, 2]","section_id":"add-data-points"},{"id":"add-data-points-ex4","language":"javascript","code":"const res8 = await client.ts.mAdd([\n  { key: 'thermometer:1', timestamp: 1, value: 9.2 },\n  { key: 'thermometer:1', timestamp: 2, value: 9.9 },\n  { key: 'thermometer:2', timestamp: 2, value: 10.3 }\n]);\nconsole.log(res8); \/\/ >>> [1, 2, 2]","section_id":"add-data-points"},{"id":"add-data-points-ex5","language":"python","code":"res8 = r.ts().madd([\n    (\"thermometer:1\", 1, 9.2),\n    (\"thermometer:1\", 2, 9.9),\n    (\"thermometer:2\", 2, 10.3)\n])\nprint(res8)  # >>> [1, 2, 2]","section_id":"add-data-points"},{"id":"query-data-points-ex0","language":"plaintext","code":"# The last recorded temperature for thermometer:2\n# was 10.3 at time 2ms.\n> TS.GET thermometer:2\n1) (integer) 2\n2) 10.3","section_id":"query-data-points"},{"id":"query-data-points-ex1","language":"csharp","code":"\/\/ The last recorded temperature for thermometer:2\n        \/\/ was 10.3 at time 2.\n        TimeSeriesTuple? res9 = db.TS().Get(\"thermometer:2\");\n        Console.WriteLine($\"({res9!.Time.Value}, {res9.Val})\");\n        \/\/ >>> (2, 10.3)","section_id":"query-data-points"},{"id":"query-data-points-ex2","language":"go","code":"\/\/ The last recorded temperature for thermometer:2\n\t\/\/ was 10.3 at time 2.\n\tres2, err := rdb.TSGet(ctx, \"thermometer:2\").Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res2)\n\t\/\/ >>> {2 10.3}","section_id":"query-data-points"},{"id":"query-data-points-ex3","language":"java","code":"\/\/ The last recorded temperature for thermometer:2\n        \/\/ was 10.3 at time 2.\n        TSElement res9 = jedis.tsGet(\"thermometer:2\");\n        System.out.println(\"(\" + res9.getTimestamp() + \", \" + res9.getValue() + \")\");\n        \/\/ >>> (2, 10.3)","section_id":"query-data-points"},{"id":"query-data-points-ex4","language":"javascript","code":"\/\/ The last recorded temperature for thermometer:2\n\/\/ was 10.3 at time 2.\nconst res9 = await client.ts.get('thermometer:2');\nconsole.log(res9); \/\/ >>> { timestamp: 2, value: 10.3 }","section_id":"query-data-points"},{"id":"query-data-points-ex5","language":"python","code":"# The last recorded temperature for thermometer:2\n# was 10.3 at time 2.\nres9 = r.ts().get(\"thermometer:2\")\nprint(res9)  # >>> (2, 10.3)","section_id":"query-data-points"},{"id":"query-data-points-ex6","language":"plaintext","code":"# Add 5 data points to a time series named \"rg:1\".\n> TS.CREATE rg:1\nOK\n> TS.MADD rg:1 0 18 rg:1 1 14 rg:1 2 22 rg:1 3 18 rg:1 4 24\n1) (integer) 0\n2) (integer) 1\n3) (integer) 2\n4) (integer) 3\n5) (integer) 4\n\n# Retrieve all the data points in ascending order.\n> TS.RANGE rg:1 - +\n1) 1) (integer) 0\n   2) 18\n2) 1) (integer) 1\n   2) 14\n3) 1) (integer) 2\n   2) 22\n4) 1) (integer) 3\n   2) 18\n5) 1) (integer) 4\n   2) 24\n\n# Retrieve data points up to time 1 (inclusive).\n> TS.RANGE rg:1 - 1\n1) 1) (integer) 0\n   2) 18\n2) 1) (integer) 1\n   2) 14\n\n# Retrieve data points from time 3 onwards.\n> TS.RANGE rg:1 3 +\n1) 1) (integer) 3\n   2) 18\n2) 1) (integer) 4\n   2) 24\n\n# Retrieve all the data points in descending order.\n> TS.REVRANGE rg:1 - +\n1) 1) (integer) 4\n   2) 24\n2) 1) (integer) 3\n   2) 18\n3) 1) (integer) 2\n   2) 22\n4) 1) (integer) 1\n   2) 14\n5) 1) (integer) 0\n   2) 18\n\n# Retrieve data points up to time 1 (inclusive), but\n# return them in descending order.\n> TS.REVRANGE rg:1 - 1\n1) 1) (integer) 1\n   2) 14\n2) 1) (integer) 0\n   2) 18","section_id":"query-data-points"},{"id":"query-data-points-ex7","language":"csharp","code":"\/\/ Add 5 data points to a time series named \"rg:1\".\n        bool res10 = db.TS().Create(\n            \"rg:1\",\n            new TsCreateParamsBuilder().build()\n        );\n        Console.WriteLine(res10); \/\/ >>> True\n\n        var sequence2 = new List<(string, TimeStamp, double)>\n        {\n            (\"rg:1\", 0, 18),\n            (\"rg:1\", 1, 14),\n            (\"rg:1\", 2, 22),\n            (\"rg:1\", 3, 18),\n            (\"rg:1\", 4, 24)\n        };\n        IReadOnlyList<TimeStamp> res11 = db.TS().MAdd(sequence2);\n        Console.WriteLine(\n            $\"[{string.Join(\", \", res11.Select(t => t.Value))}]\"\n        );\n        \/\/ >>> [0, 1, 2, 3, 4]\n\n        \/\/ Retrieve all the data points in ascending order.\n        IReadOnlyList<TimeSeriesTuple> res12 = db.TS().Range(\"rg:1\", \"-\", \"+\");\n        Console.WriteLine(\n            $\"[{string.Join(\", \", res12.Select(t => $\"({t.Time.Value}, {t.Val})\"))}]\"\n        );\n        \/\/ >>> [(0, 18), (1, 14), (2, 22), (3, 18), (4, 24)]\n\n        \/\/ Retrieve data points up to time 1 (inclusive).\n        IReadOnlyList<TimeSeriesTuple> res13 = db.TS().Range(\"rg:1\", \"-\", 1);\n        Console.WriteLine(\n            $\"[{string.Join(\", \", res13.Select(t => $\"({t.Time.Value}, {t.Val})\"))}]\"\n        );\n        \/\/ >>> [(0, 18), (1, 14)]\n\n        \/\/ Retrieve data points from time 3 onwards.\n        IReadOnlyList<TimeSeriesTuple> res14 = db.TS().Range(\"rg:1\", 3, \"+\");\n        Console.WriteLine(\n            $\"[{string.Join(\", \", res14.Select(t => $\"({t.Time.Value}, {t.Val})\"))}]\"\n        );\n        \/\/ >>> [(3, 18), (4, 24)]\n\n        \/\/ Retrieve all the data points in descending order.\n        IReadOnlyList<TimeSeriesTuple> res15 = db.TS().RevRange(\"rg:1\", \"-\", \"+\");\n        Console.WriteLine(\n            $\"[{string.Join(\", \", res15.Select(t => $\"({t.Time.Value}, {t.Val})\"))}]\"\n        );\n        \/\/ >>> [(4, 24), (3, 18), (2, 22), (1, 14), (0, 18)]\n\n        \/\/ Retrieve data points up to time 1 (inclusive), but return them\n        \/\/ in descending order.\n        IReadOnlyList<TimeSeriesTuple> res16 = db.TS().RevRange(\"rg:1\", \"-\", 1);\n        Console.WriteLine(\n            $\"[{string.Join(\", \", res16.Select(t => $\"({t.Time.Value}, {t.Val})\"))}]\"\n        );\n        \/\/ >>> [(1, 14), (0, 18)]","section_id":"query-data-points"},{"id":"query-data-points-ex8","language":"go","code":"\/\/ Add 5 data points to a time series named \"rg:1\".\n\tres1, err := rdb.TSCreate(ctx, \"rg:1\").Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res1) \/\/ >>> OK\n\n\tres2, err := rdb.TSMAdd(ctx, [][]interface{}{\n\t\t{\"rg:1\", 0, 18},\n\t\t{\"rg:1\", 1, 14},\n\t\t{\"rg:1\", 2, 22},\n\t\t{\"rg:1\", 3, 18},\n\t\t{\"rg:1\", 4, 24},\n\t}).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res2) \/\/ >>> [0 1 2 3 4]\n\n\t\/\/ Retrieve all the data points in ascending order.\n\t\/\/ Note: use 0 and `math.MaxInt64` instead of - and +\n\t\/\/ to denote the minimum and maximum possible timestamps.\n\tres3, err := rdb.TSRange(ctx, \"rg:1\", 0, math.MaxInt64).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res3)\n\t\/\/ >>> [{0 18} {1 14} {2 22} {3 18} {4 24}]\n\n\t\/\/ Retrieve data points up to time 1 (inclusive).\n\tres4, err := rdb.TSRange(ctx, \"rg:1\", 0, 1).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res4)\n\t\/\/ >>> [{0 18} {1 14}]\n\n\t\/\/ Retrieve data points from time 3 onwards.\n\tres5, err := rdb.TSRange(ctx, \"rg:1\", 3, math.MaxInt64).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res5)\n\t\/\/ >>> [{3 18} {4 24}]\n\n\t\/\/ Retrieve all the data points in descending order.\n\tres6, err := rdb.TSRevRange(ctx, \"rg:1\", 0, math.MaxInt64).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res6)\n\t\/\/ >>> [{4 24} {3 18} {2 22} {1 14} {0 18}]\n\n\t\/\/ Retrieve data points up to time 1 (inclusive), but return them\n\t\/\/ in descending order.\n\tres7, err := rdb.TSRevRange(ctx, \"rg:1\", 0, 1).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res7)\n\t\/\/ >>> [{1 14} {0 18}]","section_id":"query-data-points"},{"id":"query-data-points-ex9","language":"java","code":"\/\/ Add 5 data points to a time series named \"rg:1\"\n        String res10 = jedis.tsCreate(\"rg:1\");\n        System.out.println(res10); \/\/ >>> OK\n\n        List<Long> res11 = jedis.tsMAdd(\n            new AbstractMap.SimpleEntry<>(\"rg:1\", new TSElement(0L, 18.0)),\n            new AbstractMap.SimpleEntry<>(\"rg:1\", new TSElement(1L, 14.0)),\n            new AbstractMap.SimpleEntry<>(\"rg:1\", new TSElement(2L, 22.0)),\n            new AbstractMap.SimpleEntry<>(\"rg:1\", new TSElement(3L, 18.0)),\n            new AbstractMap.SimpleEntry<>(\"rg:1\", new TSElement(4L, 24.0))\n        );\n        System.out.println(res11); \/\/ >>> [0, 1, 2, 3, 4]\n\n        \/\/ Retrieve all the data points in ascending order\n        List<TSElement> res12 = jedis.tsRange(\"rg:1\", 0L, 4L);\n        System.out.println(res12);\n        \/\/ >>> [(0:18.0), (1:14.0), (2:22.0), (3:18.0), (4:24.0)]\n\n        \/\/ Retrieve data points up to time 1 (inclusive)\n        List<TSElement> res13 = jedis.tsRange(\"rg:1\", 0L, 1L);\n        System.out.println(res13);\n        \/\/ >>> [(0:18.0), (1:14.0)]\n\n        \/\/ Retrieve data points from time 3 onwards\n        List<TSElement> res14 = jedis.tsRange(\"rg:1\", 3L, 4L);\n        System.out.println(res14);\n        \/\/ >>> [(3:18.0), (4:24.0)]\n\n        \/\/ Retrieve all the data points in descending order\n        List<TSElement> res15 = jedis.tsRevRange(\"rg:1\", 0L, 4L);\n        System.out.println(res15);\n        \/\/ >>> [(4:24.0), (3:18.0), (2:22.0), (1:14.0), (0:18.0)]\n\n        \/\/ Retrieve data points up to time 1 (inclusive), in descending order\n        List<TSElement> res16 = jedis.tsRevRange(\"rg:1\", 0L, 1L);\n        System.out.println(res16);\n        \/\/ >>> [(1:14.0), (0:18.0)]","section_id":"query-data-points"},{"id":"query-data-points-ex10","language":"javascript","code":"\/\/ Add 5 data points to a time series named \"rg:1\".\nconst res10 = await client.ts.create('rg:1');\nconsole.log(res10); \/\/ >>> OK\n\nconst res11 = await client.ts.mAdd([\n  { key: 'rg:1', timestamp: 0, value: 18 },\n  { key: 'rg:1', timestamp: 1, value: 14 },\n  { key: 'rg:1', timestamp: 2, value: 22 },\n  { key: 'rg:1', timestamp: 3, value: 18 },\n  { key: 'rg:1', timestamp: 4, value: 24 }\n]);\nconsole.log(res11); \/\/ >>> [0, 1, 2, 3, 4]\n\n\/\/ Retrieve all the data points in ascending order.\nconst res12 = await client.ts.range('rg:1', '-', '+');\nconsole.log(res12);\n\/\/ >>> [{ timestamp: 0, value: 18 }, { timestamp: 1, value: 14 }, ...]\n\n\/\/ Retrieve data points up to time 1 (inclusive).\nconst res13 = await client.ts.range('rg:1', '-', 1);\nconsole.log(res13);\n\/\/ >>> [{ timestamp: 0, value: 18 }, { timestamp: 1, value: 14 }]\n\n\/\/ Retrieve data points from time 3 onwards.\nconst res14 = await client.ts.range('rg:1', 3, '+');\nconsole.log(res14);\n\/\/ >>> [{ timestamp: 3, value: 18 }, { timestamp: 4, value: 24 }]\n\n\/\/ Retrieve all the data points in descending order.\nconst res15 = await client.ts.revRange('rg:1', '-', '+');\nconsole.log(res15);\n\/\/ >>> [{ timestamp: 4, value: 24 }, { timestamp: 3, value: 18 }, ...]\n\n\/\/ Retrieve data points up to time 1 (inclusive), but return them\n\/\/ in descending order.\nconst res16 = await client.ts.revRange('rg:1', '-', 1);\nconsole.log(res16);\n\/\/ >>> [{ timestamp: 1, value: 14 }, { timestamp: 0, value: 18 }]","section_id":"query-data-points"},{"id":"query-data-points-ex11","language":"python","code":"# Add 5 data points to a time series named \"rg:1\".\nres10 = r.ts().create(\"rg:1\")\nprint(res10)  # >>> True\n\nres11 = r.ts().madd([\n        (\"rg:1\", 0, 18),\n        (\"rg:1\", 1, 14),\n        (\"rg:1\", 2, 22),\n        (\"rg:1\", 3, 18),\n        (\"rg:1\", 4, 24),\n])\nprint(res11)  # >>> [0, 1, 2, 3, 4]\n\n# Retrieve all the data points in ascending order.\nres12 = r.ts().range(\"rg:1\", \"-\", \"+\")\nprint(res12)  # >>> [(0, 18.0), (1, 14.0), (2, 22.0), (3, 18.0), (4, 24.0)]\n\n# Retrieve data points up to time 1 (inclusive).\nres13 = r.ts().range(\"rg:1\", \"-\", 1)\nprint(res13)  # >>> [(0, 18.0), (1, 14.0)]\n\n# Retrieve data points from time 3 onwards.\nres14 = r.ts().range(\"rg:1\", 3, \"+\")\nprint(res14)  # >>> [(3, 18.0), (4, 24.0)]\n\n# Retrieve all the data points in descending order.\nres15 = r.ts().revrange(\"rg:1\", \"-\", \"+\")\nprint(res15)  # >>> [(4, 24.0), (3, 18.0), (2, 22.0), (1, 14.0), (0, 18.0)]\n\n# Retrieve data points up to time 1 (inclusive), but return them\n# in descending order.\nres16 = r.ts().revrange(\"rg:1\", \"-\", 1)\nprint(res16)  # >>> [(1, 14.0), (0, 18.0)]","section_id":"query-data-points"},{"id":"query-data-points-ex12","language":"plaintext","code":"> TS.RANGE rg:1 - + FILTER_BY_TS 0 2 4\n1) 1) (integer) 0\n   2) 18\n2) 1) (integer) 2\n   2) 22\n3) 1) (integer) 4\n   2) 24\n> TS.REVRANGE rg:1 - + FILTER_BY_TS 0 2 4 FILTER_BY_VALUE 20 25\n1) 1) (integer) 4\n   2) 24\n2) 1) (integer) 2\n   2) 22\n> TS.REVRANGE rg:1 - + FILTER_BY_TS 0 2 4 FILTER_BY_VALUE 22 22\n1) 1) (integer) 2\n   2) 22","section_id":"query-data-points"},{"id":"query-data-points-ex13","language":"csharp","code":"var filterByTs = new List<TimeStamp> { 0, 2, 4 };\n        IReadOnlyList<TimeSeriesTuple> res17 = db.TS().Range(\n            \"rg:1\", \"-\", \"+\", filterByTs: filterByTs\n        );\n        Console.WriteLine(\n            $\"[{string.Join(\", \", res17.Select(t => $\"({t.Time.Value}, {t.Val})\"))}]\"\n        );\n        \/\/ >>> [(0, 18), (2, 22), (4, 24)]\n\n        IReadOnlyList<TimeSeriesTuple> res18 = db.TS().RevRange(\n            \"rg:1\", \"-\", \"+\",\n            filterByTs: filterByTs,\n            filterByValue: (20, 25)\n        );\n        Console.WriteLine(\n            $\"[{string.Join(\", \", res18.Select(t => $\"({t.Time.Value}, {t.Val})\"))}]\"\n        );\n        \/\/ >>> [(4, 24), (2, 22)]\n\n        IReadOnlyList<TimeSeriesTuple> res19 = db.TS().RevRange(\n            \"rg:1\", \"-\", \"+\",\n            filterByTs: filterByTs,\n            filterByValue: (22, 22),\n            count: 1\n        );\n        Console.WriteLine(\n            $\"[{string.Join(\", \", res19.Select(t => $\"({t.Time.Value}, {t.Val})\"))}]\"\n        );\n        \/\/ >>> [(2, 22)]","section_id":"query-data-points"},{"id":"query-data-points-ex14","language":"go","code":"res8, err := rdb.TSRangeWithArgs(\n\t\tctx,\n\t\t\"rg:1\",\n\t\t0,\n\t\tmath.MaxInt64,\n\t\t&redis.TSRangeOptions{\n\t\t\tFilterByTS: []int{0, 2, 4},\n\t\t},\n\t).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res8) \/\/ >>> [{0 18} {2 22} {4 24}]\n\n\tres9, err := rdb.TSRevRangeWithArgs(\n\t\tctx,\n\t\t\"rg:1\",\n\t\t0,\n\t\tmath.MaxInt64,\n\t\t&redis.TSRevRangeOptions{\n\t\t\tFilterByTS:    []int{0, 2, 4},\n\t\t\tFilterByValue: []int{20, 25},\n\t\t},\n\t).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res9) \/\/ >>> [{4 24} {2 22}]\n\n\tres10, err := rdb.TSRevRangeWithArgs(\n\t\tctx,\n\t\t\"rg:1\",\n\t\t0,\n\t\tmath.MaxInt64,\n\t\t&redis.TSRevRangeOptions{\n\t\t\tFilterByTS:    []int{0, 2, 4},\n\t\t\tFilterByValue: []int{22, 22},\n\t\t},\n\t).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res10) \/\/ >>> [{2 22}]","section_id":"query-data-points"},{"id":"query-data-points-ex15","language":"java","code":"List<TSElement> res17 = jedis.tsRange(\"rg:1\",  \n            TSRangeParams.rangeParams()\n                .fromTimestamp(0L)\n                .toTimestamp(4L)\n                .filterByTS(0L, 2L, 4L)\n        );\n        System.out.println(res17);\n        \/\/ >>> [(0:18.0), (2:22.0), (4:24.0)]\n\n        List<TSElement> res18 = jedis.tsRevRange(\"rg:1\",\n            TSRangeParams.rangeParams()\n                .fromTimestamp(0L)\n                .toTimestamp(4L)\n                .filterByTS(0L, 2L, 4L)\n                .filterByValues(20.0, 25.0)\n        );\n        System.out.println(res18);\n        \/\/ >>> [(4:24.0), (2:22.0)]\n\n        List<TSElement> res19 = jedis.tsRevRange(\"rg:1\",\n            TSRangeParams.rangeParams()\n                .fromTimestamp(0L)\n                .toTimestamp(4L)\n                .filterByTS(0L, 2L, 4L)\n                .filterByValues(22.0, 22.0)\n                .count(1)\n        );\n        System.out.println(res19);\n        \/\/ >>> [(2:22.0)]","section_id":"query-data-points"},{"id":"query-data-points-ex16","language":"javascript","code":"const res17 = await client.ts.range('rg:1', '-', '+', {\n  FILTER_BY_TS: [0, 2, 4]\n});\nconsole.log(res17);\n\/\/ >>> [{ timestamp: 0, value: 18 }, { timestamp: 2, value: 22 }, { timestamp: 4, value: 24 }]\n\nconst res18 = await client.ts.revRange('rg:1', '-', '+', {\n  FILTER_BY_TS: [0, 2, 4],\n  FILTER_BY_VALUE: { min: 20, max: 25 }\n});\nconsole.log(res18);\n\/\/ >>> [{ timestamp: 4, value: 24 }, { timestamp: 2, value: 22 }]\n\nconst res19 = await client.ts.revRange('rg:1', '-', '+', {\n  FILTER_BY_TS: [0, 2, 4],\n  FILTER_BY_VALUE: { min: 22, max: 22 },\n  COUNT: 1\n});\nconsole.log(res19);\n\/\/ >>> [{ timestamp: 2, value: 22 }]","section_id":"query-data-points"},{"id":"query-data-points-ex17","language":"python","code":"res17 = r.ts().range(\"rg:1\", \"-\", \"+\", filter_by_ts=[0, 2, 4])\nprint(res17)  # >>> [(0, 18.0), (2, 22.0), (4, 24.0)]\n\nres18 = r.ts().revrange(\n    \"rg:1\", \"-\", \"+\",\n    filter_by_ts=[0, 2, 4],\n    filter_by_min_value=20,\n    filter_by_max_value=25,\n)\nprint(res18)  # >>> [(4, 24.0), (2, 22.0)]\n\nres19 = r.ts().revrange(\n    \"rg:1\", \"-\", \"+\",\n    filter_by_ts=[0, 2, 4],\n    filter_by_min_value=22,\n    filter_by_max_value=22,\n    count=1,\n)\nprint(res19)  # >>> [(2, 22.0)]","section_id":"query-data-points"},{"id":"query-multiple-time-series-ex0","language":"plaintext","code":"# Create three new \"rg:\" time series (two in the US\n# and one in the UK, with different units) and add some\n# data points.\n> TS.CREATE rg:2 LABELS location us unit cm\nOK\n> TS.CREATE rg:3 LABELS location us unit in\nOK\n> TS.CREATE rg:4 LABELS location uk unit mm\nOK\n> TS.MADD rg:2 0 1.8 rg:3 0 0.9 rg:4 0 25\n1) (integer) 0\n2) (integer) 0\n3) (integer) 0\n> TS.MADD rg:2 1 2.1 rg:3 1 0.77 rg:4 1 18\n1) (integer) 1\n2) (integer) 1\n3) (integer) 1\n> TS.MADD rg:2 2 2.3 rg:3 2 1.1 rg:4 2 21\n1) (integer) 2\n2) (integer) 2\n3) (integer) 2\n> TS.MADD rg:2 3 1.9 rg:3 3 0.81 rg:4 3 19\n1) (integer) 3\n2) (integer) 3\n3) (integer) 3\n> TS.MADD rg:2 4 1.78 rg:3 4 0.74 rg:4 4 23\n1) (integer) 4\n2) (integer) 4\n3) (integer) 4\n\n# Retrieve the last data point from each US time series. If\n# you don't specify any labels, an empty array is returned\n# for the labels.\n> TS.MGET FILTER location=us\n1) 1) \"rg:2\"\n   2) (empty array)\n   3) 1) (integer) 4\n      2) 1.78\n2) 1) \"rg:3\"\n   2) (empty array)\n   3) 1) (integer) 4\n      2) 7.4E-1\n\n# Retrieve the same data points, but include the `unit`\n# label in the results.\n> TS.MGET SELECTED_LABELS unit FILTER location=us\n1) 1) \"rg:2\"\n   2) 1) 1) \"unit\"\n         2) \"cm\"\n   3) 1) (integer) 4\n      2) 1.78\n2) 1) \"rg:3\"\n   2) 1) 1) \"unit\"\n         2) \"in\"\n   3) 1) (integer) 4\n      2) 7.4E-1\n\n# Retrieve data points up to time 2 (inclusive) from all\n# time series that use millimeters as the unit. Include all\n# labels in the results.\n> TS.MRANGE - 2 WITHLABELS FILTER unit=mm\n1) 1) \"rg:4\"\n   2) 1) 1) \"location\"\n         2) \"uk\"\n      2) 1) \"unit\"\n         2) \"mm\"\n   3) 1) 1) (integer) 0\n         2) 25\n      2) 1) (integer) 1\n         2) 18\n      3) 1) (integer) 2\n         2) 21\n\n# Retrieve data points from time 1 to time 3 (inclusive) from\n# all time series that use centimeters or millimeters as the unit,\n# but only return the `location` label. Return the results\n# in descending order of timestamp.\n> TS.MREVRANGE 1 3 SELECTED_LABELS location FILTER unit=(cm,mm)\n1) 1) \"rg:2\"\n   2) 1) 1) \"location\"\n         2) \"us\"\n   3) 1) 1) (integer) 3\n         2) 1.9\n      2) 1) (integer) 2\n         2) 2.3\n      3) 1) (integer) 1\n         2) 2.1\n2) 1) \"rg:4\"\n2) 1) 1) \"location\"\n         2) \"uk\"\n   3) 1) 1) (integer) 3\n         2) 19\n      2) 1) (integer) 2\n         2) 21\n      3) 1) (integer) 1\n         2) 18","section_id":"query-multiple-time-series"},{"id":"query-multiple-time-series-ex1","language":"csharp","code":"\/\/ Create three new \"rg:\" time series (two in the US\n        \/\/ and one in the UK, with different units) and add some\n        \/\/ data points.\n        var labels2 = new List<TimeSeriesLabel>\n        {\n            new(\"location\", \"us\"),\n            new(\"unit\", \"cm\")\n        };\n        bool res20 = db.TS().Create(\n            \"rg:2\",\n            new TsCreateParamsBuilder()\n                .AddLabels(labels2)\n                .build()\n        );\n        Console.WriteLine(res20); \/\/ >>> True\n\n        var labels3 = new List<TimeSeriesLabel>\n        {\n            new(\"location\", \"us\"),\n            new(\"unit\", \"in\")\n        };\n\n        bool res21 = db.TS().Create(\n            \"rg:3\",\n            new TsCreateParamsBuilder()\n                .AddLabels(labels3)\n                .build()\n        );\n        Console.WriteLine(res21); \/\/ >>> True\n\n        var labels4 = new List<TimeSeriesLabel>\n        {\n            new(\"location\", \"uk\"),\n            new(\"unit\", \"mm\")\n        };\n        bool res22 = db.TS().Create(\n            \"rg:4\",\n            new TsCreateParamsBuilder()\n                .AddLabels(labels4)\n                .build()\n        );\n        Console.WriteLine(res22); \/\/ >>> True\n\n        var sequence3 = new List<(string, TimeStamp, double)>\n        {\n            (\"rg:2\", 0, 1.8),\n            (\"rg:3\", 0, 0.9),\n            (\"rg:4\", 0, 25)\n        };\n        IReadOnlyList<TimeStamp> res23 = db.TS().MAdd(sequence3);\n        Console.WriteLine(\n            $\"[{string.Join(\", \", res23.Select(t => t.Value))}]\"\n        );\n        \/\/ >>> [0, 0, 0]\n\n        var sequence4 = new List<(string, TimeStamp, double)>\n        {\n            (\"rg:2\", 1, 2.1),\n            (\"rg:3\", 1, 0.77),\n            (\"rg:4\", 1, 18)\n        };\n\n        IReadOnlyList<TimeStamp> res24 = db.TS().MAdd(sequence4);\n        Console.WriteLine(\n            $\"[{string.Join(\", \", res24.Select(t => t.Value))}]\"\n        );\n        \/\/ >>> [1, 1, 1]\n\n        var sequence5 = new List<(string, TimeStamp, double)>\n        {\n            (\"rg:2\", 2, 2.3),\n            (\"rg:3\", 2, 1.1),\n            (\"rg:4\", 2, 21)\n        };\n\n        IReadOnlyList<TimeStamp> res25 = db.TS().MAdd(sequence5);\n        Console.WriteLine(\n            $\"[{string.Join(\", \", res25.Select(t => t.Value))}]\"\n        );\n        \/\/ >>> [2, 2, 2]\n\n        var sequence6 = new List<(string, TimeStamp, double)>\n        {\n            (\"rg:2\", 3, 1.9),\n            (\"rg:3\", 3, 0.81),\n            (\"rg:4\", 3, 19)\n        };\n\n        IReadOnlyList<TimeStamp> res26 = db.TS().MAdd(sequence6);\n        Console.WriteLine(\n            $\"[{string.Join(\", \", res26.Select(t => t.Value))}]\"\n        );\n        \/\/ >>> [3, 3, 3]\n\n        var sequence7 = new List<(string, TimeStamp, double)>\n        {\n            (\"rg:2\", 4, 1.78),\n            (\"rg:3\", 4, 0.74),\n            (\"rg:4\", 4, 23)\n        };\n        IReadOnlyList<TimeStamp> res27 = db.TS().MAdd(sequence7);\n        Console.WriteLine(\n            $\"[{string.Join(\", \", res27.Select(t => t.Value))}]\"\n        );\n        \/\/ >>> [4, 4, 4]\n\n        \/\/ Retrieve the last data point from each US time series. If\n        \/\/ you don't specify any labels, an empty array is returned\n        \/\/ for the labels.\n        var filters = new List<string> { \"location=us\" };\n        var res28 = db.TS().MGet(filters);\n        Console.WriteLine(res28.Count); \/\/ >>> 2\n\n        foreach (var (key, labelsResult, value) in res28)\n        {\n            Console.WriteLine($\"{key}: ({value.Time.Value}, {value.Val})\");\n        }\n        \/\/ >>> rg:2: (4, 1.78)\n        \/\/ >>> rg:3: (4, 0.74)\n\n        \/\/ Retrieve the same data points, but include the `unit`\n        \/\/ label in the results.\n        var selectUnitLabel = new List<string> { \"unit\" };\n\n        var res29 = db.TS().MGet(\n            filters,\n            selectedLabels: selectUnitLabel\n        );\n        Console.WriteLine(res29.Count); \/\/ >>> 2\n\n        foreach (var (key, labelsResult, value) in res29)\n        {\n            var unitLabel = labelsResult.FirstOrDefault(l => l.Key == \"unit\");\n            Console.WriteLine($\"{key} (unit: {unitLabel?.Value}): ({value.Time.Value}, {value.Val})\");\n        }\n        \/\/ >>> rg:2 (unit: cm): (4, 1.78)\n        \/\/ >>> rg:3 (unit: in): (4, 0.74)\n\n        \/\/ Retrieve data points up to time 2 (inclusive) from all\n        \/\/ time series that use millimeters as the unit. Include all\n        \/\/ labels in the results.\n        var mmFilters = new List<string> { \"unit=mm\" };\n\n        IReadOnlyList<\n            (string, IReadOnlyList<TimeSeriesLabel>, IReadOnlyList<TimeSeriesTuple>)\n        > res30 = db.TS().MRange(\n            \"-\", 2, mmFilters, withLabels: true\n        );\n        Console.WriteLine(res30.Count); \/\/ >>> 1\n\n        foreach (var (key, labelsResult, values) in res30)\n        {\n            Console.WriteLine($\"{key}:\");\n            Console.WriteLine($\"  Labels: ({string.Join(\", \", labelsResult.Select(l => $\"{l.Key}={l.Value}\"))})\");\n            Console.WriteLine($\"  Values: [{string.Join(\", \", values.Select(t => $\"({t.Time.Value}, {t.Val})\"))}]\");\n        }\n        \/\/ >>> rg:4:\n        \/\/ >>>   Labels:location=uk,unit=mm\n        \/\/ >>>   Values: [(1, 23), (2, 21), (3, 19)]\n\n        \/\/ Retrieve data points from time 1 to time 3 (inclusive) from\n        \/\/ all time series that use centimeters or millimeters as the unit,\n        \/\/ but only return the `location` label. Return the results\n        \/\/ in descending order of timestamp.\n        var cmMmFilters = new List<string> { \"unit=(cm,mm)\" };\n        var locationLabels = new List<string> { \"location\" };\n        IReadOnlyList<\n            (string, IReadOnlyList<TimeSeriesLabel>, IReadOnlyList<TimeSeriesTuple>)\n        > res31 = db.TS().MRevRange(\n            1, 3, cmMmFilters, selectLabels: locationLabels\n        );\n        Console.WriteLine(res31.Count); \/\/ >>> 2\n\n        foreach (var (key, labelsResult, values) in res31)\n        {\n            var locationLabel = labelsResult.FirstOrDefault(l => l.Key == \"location\");\n            Console.WriteLine($\"{key} (location: {locationLabel?.Value})\");\n            Console.WriteLine($\"  Values: [{string.Join(\", \", values.Select(t => $\"({t.Time.Value}, {t.Val})\"))}]\");\n        }\n        \/\/ >>> rg:4 (location: uk)\n        \/\/ >>>   Values: [(3, 19), (2, 21), (1, 23)]\n        \/\/ >>> rg:2 (location: us)\n        \/\/ >>>   Values: [(3, 2.3), (2, 2.1), (1, 1.8)]","section_id":"query-multiple-time-series"},{"id":"query-multiple-time-series-ex2","language":"go","code":"\/\/ Create three new \"rg:\" time series (two in the US\n\t\/\/ and one in the UK, with different units) and add some\n\t\/\/ data points.\n\tres20, err := rdb.TSCreateWithArgs(ctx, \"rg:2\", &redis.TSOptions{\n\t\tLabels: map[string]string{\"location\": \"us\", \"unit\": \"cm\"},\n\t}).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res20) \/\/ >>> OK\n\n\tres21, err := rdb.TSCreateWithArgs(ctx, \"rg:3\", &redis.TSOptions{\n\t\tLabels: map[string]string{\"location\": \"us\", \"unit\": \"in\"},\n\t}).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res21) \/\/ >>> OK\n\n\tres22, err := rdb.TSCreateWithArgs(ctx, \"rg:4\", &redis.TSOptions{\n\t\tLabels: map[string]string{\"location\": \"uk\", \"unit\": \"mm\"},\n\t}).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res22) \/\/ >>> OK\n\n\tres23, err := rdb.TSMAdd(ctx, [][]interface{}{\n\t\t{\"rg:2\", 0, 1.8},\n\t\t{\"rg:3\", 0, 0.9},\n\t\t{\"rg:4\", 0, 25},\n\t}).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res23) \/\/ >>> [0 0 0]\n\n\tres24, err := rdb.TSMAdd(ctx, [][]interface{}{\n\t\t{\"rg:2\", 1, 2.1},\n\t\t{\"rg:3\", 1, 0.77},\n\t\t{\"rg:4\", 1, 18},\n\t}).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res24) \/\/ >>> [1 1 1]\n\n\tres25, err := rdb.TSMAdd(ctx, [][]interface{}{\n\t\t{\"rg:2\", 2, 2.3},\n\t\t{\"rg:3\", 2, 1.1},\n\t\t{\"rg:4\", 2, 21},\n\t}).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res25) \/\/ >>> [2 2 2]\n\n\tres26, err := rdb.TSMAdd(ctx, [][]interface{}{\n\t\t{\"rg:2\", 3, 1.9},\n\t\t{\"rg:3\", 3, 0.81},\n\t\t{\"rg:4\", 3, 19},\n\t}).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res26) \/\/ >>> [3 3 3]\n\n\tres27, err := rdb.TSMAdd(ctx, [][]interface{}{\n\t\t{\"rg:2\", 4, 1.78},\n\t\t{\"rg:3\", 4, 0.74},\n\t\t{\"rg:4\", 4, 23},\n\t}).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res27) \/\/ >>> [4 4 4]\n\n\t\/\/ Retrieve the last data point from each US time series.\n\tres28, err := rdb.TSMGet(ctx, []string{\"location=us\"}).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tres28Keys := slices.Collect(maps.Keys(res28))\n\tsort.Strings(res28Keys)\n\n\tfor _, k := range res28Keys {\n\t\tlabels := res28[k][0].(map[interface{}]interface{})\n\n\t\tlabelKeys := make([]string, 0, len(labels))\n\n\t\tfor lk := range labels {\n\t\t\tlabelKeys = append(labelKeys, lk.(string))\n\t\t}\n\n\t\tsort.Strings(labelKeys)\n\n\t\tfmt.Printf(\"%v:\\n\", k)\n\n\t\tfor _, lk := range labelKeys {\n\t\t\tfmt.Printf(\"  %v: %v\\n\", lk, labels[lk])\n\t\t}\n\n\t\tfmt.Printf(\"  %v\\n\", res28[k][1])\n\t}\n\t\/\/ >>> rg:2:\n\t\/\/ >>>   {4 1.78}\n\t\/\/ >>> rg:3:\n\t\/\/ >>>   {4 0.74}\n\n\t\/\/ Retrieve the same data points, but include the `unit`\n\t\/\/ label in the results.\n\tres29, err := rdb.TSMGetWithArgs(\n\t\tctx,\n\t\t[]string{\"location=us\"},\n\t\t&redis.TSMGetOptions{\n\t\t\tSelectedLabels: []interface{}{\"unit\"},\n\t\t},\n\t).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tres29Keys := slices.Collect(maps.Keys(res29))\n\tsort.Strings(res29Keys)\n\n\tfor _, k := range res29Keys {\n\t\tlabels := res29[k][0].(map[interface{}]interface{})\n\n\t\tlabelKeys := make([]string, 0, len(labels))\n\n\t\tfor lk := range labels {\n\t\t\tlabelKeys = append(labelKeys, lk.(string))\n\t\t}\n\n\t\tsort.Strings(labelKeys)\n\n\t\tfmt.Printf(\"%v:\\n\", k)\n\n\t\tfor _, lk := range labelKeys {\n\t\t\tfmt.Printf(\"  %v: %v\\n\", lk, labels[lk])\n\t\t}\n\n\t\tfmt.Printf(\"  %v\\n\", res29[k][1])\n\t}\n\n\t\/\/ >>> rg:2:\n\t\/\/ >>>   unit: cm\n\t\/\/ >>>   [4 1.78]\n\t\/\/ >>> rg:3:\n\t\/\/ >>>   unit: in\n\t\/\/ >>>   [4 0.74]\n\n\t\/\/ Retrieve data points up to time 2 (inclusive) from all\n\t\/\/ time series that use millimeters as the unit. Include all\n\t\/\/ labels in the results.\n\t\/\/ Note that the `aggregators` field is empty if you don't\n\t\/\/ specify any aggregators.\n\tres30, err := rdb.TSMRangeWithArgs(\n\t\tctx,\n\t\t0,\n\t\t2,\n\t\t[]string{\"unit=mm\"},\n\t\t&redis.TSMRangeOptions{\n\t\t\tWithLabels: true,\n\t\t},\n\t).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tres30Keys := slices.Collect(maps.Keys(res30))\n\tsort.Strings(res30Keys)\n\n\tfor _, k := range res30Keys {\n\t\tlabels := res30[k][0].(map[interface{}]interface{})\n\t\tlabelKeys := make([]string, 0, len(labels))\n\n\t\tfor lk := range labels {\n\t\t\tlabelKeys = append(labelKeys, lk.(string))\n\t\t}\n\n\t\tsort.Strings(labelKeys)\n\n\t\tfmt.Printf(\"%v:\\n\", k)\n\n\t\tfor _, lk := range labelKeys {\n\t\t\tfmt.Printf(\"  %v: %v\\n\", lk, labels[lk])\n\t\t}\n\n\t\tfmt.Printf(\"  Aggregators: %v\\n\", res30[k][1])\n\t\tfmt.Printf(\"  %v\\n\", res30[k][2])\n\t}\n\t\/\/ >>> rg:4:\n\t\/\/ >>>   location: uk\n\t\/\/ >>>   unit: mm\n\t\/\/ >>>   Aggregators: map[aggregators:[]]\n\t\/\/ >>>   [{0 25} {1 18} {2 21}]\n\n\t\/\/ Retrieve data points from time 1 to time 3 (inclusive) from\n\t\/\/ all time series that use centimeters or millimeters as the unit,\n\t\/\/ but only return the `location` label. Return the results\n\t\/\/ in descending order of timestamp.\n\tres31, err := rdb.TSMRevRangeWithArgs(\n\t\tctx,\n\t\t1,\n\t\t3,\n\t\t[]string{\"unit=(cm,mm)\"},\n\t\t&redis.TSMRevRangeOptions{\n\t\t\tSelectedLabels: []interface{}{\"location\"},\n\t\t},\n\t).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tres31Keys := slices.Collect(maps.Keys(res31))\n\tsort.Strings(res31Keys)\n\n\tfor _, k := range res31Keys {\n\t\tlabels := res31[k][0].(map[interface{}]interface{})\n\t\tlabelKeys := make([]string, 0, len(labels))\n\n\t\tfor lk := range labels {\n\t\t\tlabelKeys = append(labelKeys, lk.(string))\n\t\t}\n\n\t\tsort.Strings(labelKeys)\n\n\t\tfmt.Printf(\"%v:\\n\", k)\n\n\t\tfor _, lk := range labelKeys {\n\t\t\tfmt.Printf(\"  %v: %v\\n\", lk, labels[lk])\n\t\t}\n\n\t\tfmt.Printf(\"  Aggregators: %v\\n\", res31[k][1])\n\t\tfmt.Printf(\"  %v\\n\", res31[k][2])\n\t}\n\t\/\/ >>> rg:2:\n\t\/\/ >>>   location: us\n\t\/\/ >>>   Aggregators: map[aggregators:[]]\n\t\/\/ >>>   [{3 1.9} {2 2.3} {1 2.1}]\n\t\/\/ >>> rg:4:\n\t\/\/ >>>   location: uk\n\t\/\/ >>>   Aggregators: map[aggregators:[]]\n\t\/\/ >>>   [{3 19} {2 21} {1 18}]","section_id":"query-multiple-time-series"},{"id":"query-multiple-time-series-ex3","language":"java","code":"\/\/ Create three new \"rg:\" time series (two in the US\n        \/\/ and one in the UK, with different units) and add some\n        \/\/ data points.\n        Map<String, String> usLabels1 = new HashMap<>();\n        usLabels1.put(\"location\", \"us\");\n        usLabels1.put(\"unit\", \"cm\");\n        \n        Map<String, String> usLabels2 = new HashMap<>();\n        usLabels2.put(\"location\", \"us\");\n        usLabels2.put(\"unit\", \"in\");\n        \n        Map<String, String> ukLabels = new HashMap<>();\n        ukLabels.put(\"location\", \"uk\");\n        ukLabels.put(\"unit\", \"mm\");\n\n        String res20 = jedis.tsCreate(\"rg:2\",\n            TSCreateParams.createParams().labels(usLabels1));\n        System.out.println(res20); \/\/ >>> OK\n\n        String res21 = jedis.tsCreate(\"rg:3\",\n            TSCreateParams.createParams().labels(usLabels2));\n        System.out.println(res21); \/\/ >>> OK\n\n        String res22 = jedis.tsCreate(\"rg:4\",\n            TSCreateParams.createParams().labels(ukLabels));\n        System.out.println(res22); \/\/ >>> OK\n\n        List<Long> res23 = jedis.tsMAdd(\n            new AbstractMap.SimpleEntry<>(\"rg:2\", new TSElement(0L, 1.8)),\n            new AbstractMap.SimpleEntry<>(\"rg:3\", new TSElement(0L, 0.9)),\n            new AbstractMap.SimpleEntry<>(\"rg:4\", new TSElement(0L, 25.0))\n        );\n        System.out.println(res23); \/\/ >>> [0, 0, 0]\n\n        List<Long> res24 = jedis.tsMAdd(\n            new AbstractMap.SimpleEntry<>(\"rg:2\", new TSElement(1L, 2.1)),\n            new AbstractMap.SimpleEntry<>(\"rg:3\", new TSElement(1L, 0.77)),\n            new AbstractMap.SimpleEntry<>(\"rg:4\", new TSElement(1L, 18.0))\n        );\n        System.out.println(res24); \/\/ >>> [1, 1, 1]\n\n        List<Long> res25 = jedis.tsMAdd(\n            new AbstractMap.SimpleEntry<>(\"rg:2\", new TSElement(2L, 2.3)),\n            new AbstractMap.SimpleEntry<>(\"rg:3\", new TSElement(2L, 1.1)),\n            new AbstractMap.SimpleEntry<>(\"rg:4\", new TSElement(2L, 21.0))\n        );\n        System.out.println(res25); \/\/ >>> [2, 2, 2]\n        \n        List<Long> res26 = jedis.tsMAdd(\n            new AbstractMap.SimpleEntry<>(\"rg:2\", new TSElement(3L, 1.9)),\n            new AbstractMap.SimpleEntry<>(\"rg:3\", new TSElement(3L, 0.81)),\n            new AbstractMap.SimpleEntry<>(\"rg:4\", new TSElement(3L, 19.0))\n        );\n        System.out.println(res26); \/\/ >>> [3, 3, 3]\n\n        List<Long> res27 = jedis.tsMAdd(\n            new AbstractMap.SimpleEntry<>(\"rg:2\", new TSElement(4L, 1.78)),\n            new AbstractMap.SimpleEntry<>(\"rg:3\", new TSElement(4L, 0.74)),\n            new AbstractMap.SimpleEntry<>(\"rg:4\", new TSElement(4L, 23.0))\n        );\n        System.out.println(res27); \/\/ >>> [4, 4, 4]\n\n        \/\/ Retrieve the last data point from each US time series.\n        Map<String, TSMGetElement> res28 = jedis.tsMGet(\n            TSMGetParams.multiGetParams().latest(),\n             \"location=us\"\n        );\n        System.out.println(res28);\n        \/\/ >>> {rg:2=TSMGetElement{key=rg:2, labels={}, element=(4:1.78)}...\n\n        \/\/ Retrieve the same data points, but include the `unit`\n        \/\/ label in the results.\n        Map<String, TSMGetElement> res29 = jedis.tsMGet(\n            TSMGetParams.multiGetParams().selectedLabels(\"unit\"), \n            \"location=us\"\n        );\n        System.out.println(res29);\n        \/\/ >>> {rg:2=TSMGetElement{key=rg:2, labels={unit=cm}, element=(4:1.78)}...\n\n        \/\/ Retrieve data points up to time 2 (inclusive) from all\n        \/\/ time series that use millimeters as the unit. Include all\n        \/\/ labels in the results.\n        Map<String, TSMRangeElements> res30 = jedis.tsMRange(\n            TSMRangeParams.multiRangeParams(0L, 2L)\n                .withLabels()\n                .filter(\"unit=mm\")\n        );\n        System.out.println(res30);\n        \/\/ >>> {rg:4=TSMRangeElements{key=rg:4, labels={location=uk, unit=mm}, value=[(0:25.0), (1:18.0), (2:21.0)]}}\n\n        \/\/ Retrieve data points from time 1 to time 3 (inclusive) from\n        \/\/ all time series that use centimeters or millimeters as the unit,\n        \/\/ but only return the `location` label. Return the results\n        \/\/ in descending order of timestamp.\n        Map<String, TSMRangeElements> res31 = jedis.tsMRevRange(\n            TSMRangeParams.multiRangeParams(1L, 3L)\n                .selectedLabels(\"location\")\n                .filter(\"unit=(cm,mm)\")\n        );\n        System.out.println(res31);\n        \/\/ >>> {rg:2=TSMRangeElements{key=rg:2, labels={location=us, unit=cm}, value=[(1:2.1)...","section_id":"query-multiple-time-series"},{"id":"query-multiple-time-series-ex4","language":"javascript","code":"\/\/ Create three new \"rg:\" time series (two in the US\n\/\/ and one in the UK, with different units) and add some\n\/\/ data points.\nconst res20 = await client.ts.create('rg:2', {\n  LABELS: { location: 'us', unit: 'cm' }\n});\nconsole.log(res20); \/\/ >>> OK\n\nconst res21 = await client.ts.create('rg:3', {\n  LABELS: { location: 'us', unit: 'in' }\n});\nconsole.log(res21); \/\/ >>> OK\n\nconst res22 = await client.ts.create('rg:4', {\n  LABELS: { location: 'uk', unit: 'mm' }\n});\nconsole.log(res22); \/\/ >>> OK\n\nconst res23 = await client.ts.mAdd([\n  { key: 'rg:2', timestamp: 0, value: 1.8 },\n  { key: 'rg:3', timestamp: 0, value: 0.9 },\n  { key: 'rg:4', timestamp: 0, value: 25 }\n]);\nconsole.log(res23); \/\/ >>> [0, 0, 0]\n\nconst res24 = await client.ts.mAdd([\n  { key: 'rg:2', timestamp: 1, value: 2.1 },\n  { key: 'rg:3', timestamp: 1, value: 0.77 },\n  { key: 'rg:4', timestamp: 1, value: 18 }\n]);\nconsole.log(res24); \/\/ >>> [1, 1, 1]\n\nconst res25 = await client.ts.mAdd([\n  { key: 'rg:2', timestamp: 2, value: 2.3 },\n  { key: 'rg:3', timestamp: 2, value: 1.1 },\n  { key: 'rg:4', timestamp: 2, value: 21 }\n]);\nconsole.log(res25); \/\/ >>> [2, 2, 2]\n\nconst res26 = await client.ts.mAdd([\n  { key: 'rg:2', timestamp: 3, value: 1.9 },\n  { key: 'rg:3', timestamp: 3, value: 0.81 },\n  { key: 'rg:4', timestamp: 3, value: 19 }\n]);\nconsole.log(res26); \/\/ >>> [3, 3, 3]\n\nconst res27 = await client.ts.mAdd([\n  { key: 'rg:2', timestamp: 4, value: 1.78 },\n  { key: 'rg:3', timestamp: 4, value: 0.74 },\n  { key: 'rg:4', timestamp: 4, value: 23 }\n]);\nconsole.log(res27); \/\/ >>> [4, 4, 4]\n\n\/\/ Retrieve the last data point from each US time series.\nconst res28 = await client.ts.mGet(['location=us']);\nconsole.log(res28);\n\/\/ >>> { \"rg:2\": { sample: { timestamp: 4, value: 1.78 } }, \"rg:3\": { sample: { timestamp: 4, value: 0.74 } } }\n\n\/\/ Retrieve the same data points, but include the `unit`\n\/\/ label in the results.\nconst res29 = await client.ts.mGetSelectedLabels(['location=us'], ['unit']);\nconsole.log(res29);\n\/\/ >>> { \"rg:2\": { labels: { unit: 'cm' }, sample: { timestamp: 4, value: 1.78 } }, \"rg:3\": { labels: { unit: 'in' }, sample: { timestamp: 4, value: 0.74 } } }\n\n\/\/ Retrieve data points up to time 2 (inclusive) from all\n\/\/ time series that use millimeters as the unit. Include all\n\/\/ labels in the results.\nconst res30 = await client.ts.mRangeWithLabels('-', 2, 'unit=mm');\nconsole.log(res30);\n\/\/ >>> { \"rg:4\": { labels: { location: 'uk', unit: 'mm' }, samples: [\n\/\/   { timestamp: 0, value: 25 },\n\/\/   { timestamp: 1, value: 18 },\n\/\/   { timestamp: 2, value: 21 }\n\/\/ ] } }\n\n\/\/ Retrieve data points from time 1 to time 3 (inclusive) from\n\/\/ all time series that use centimeters or millimeters as the unit,\n\/\/ but only return the `location` label. Return the results\n\/\/ in descending order of timestamp.\nconst res31 = await client.ts.mRevRangeSelectedLabels(\n  1, 3,\n  ['location'],\n  ['unit=(cm,mm)']\n);\nconsole.log(res31);\n\/\/ >>> { \"rg:2\": { labels: { location: 'us' }, samples: [\n\/\/   { timestamp: 3, value: 1.9 },\n\/\/   { timestamp: 2, value: 2.3 },\n\/\/   { timestamp: 1, value: 2.1 }\n\/\/ ] }, \"rg:4\": { labels: { location: 'uk' }, samples: [\n\/\/   { timestamp: 3, value: 19 },\n\/\/   { timestamp: 2, value: 21 },\n\/\/   { timestamp: 1, value: 18 }\n\/\/ ] } }","section_id":"query-multiple-time-series"},{"id":"query-multiple-time-series-ex5","language":"python","code":"# Create three new \"rg:\" time series (two in the US\n# and one in the UK, with different units) and add some\n# data points.\nres20 = r.ts().create(\n    \"rg:2\",\n    labels={\"location\": \"us\", \"unit\": \"cm\"},\n)\nprint(res20)  # >>> True\n\nres21 = r.ts().create(\n    \"rg:3\",\n    labels={\"location\": \"us\", \"unit\": \"in\"},\n)\nprint(res21)  # >>> True\n\nres22 = r.ts().create(\n    \"rg:4\",\n    labels={\"location\": \"uk\", \"unit\": \"mm\"},\n)\nprint(res22)  # >>> True\n\nres23 = r.ts().madd([\n        (\"rg:2\", 0, 1.8),\n        (\"rg:3\", 0, 0.9),\n        (\"rg:4\", 0, 25),\n])\nprint(res23)  # >>> [0, 0, 0]\n\nres24 = r.ts().madd([\n        (\"rg:2\", 1, 2.1),\n        (\"rg:3\", 1, 0.77),\n        (\"rg:4\", 1, 18),\n])\nprint(res24)  # >>> [1, 1, 1]\n\nres25 = r.ts().madd([\n        (\"rg:2\", 2, 2.3),\n        (\"rg:3\", 2, 1.1),\n        (\"rg:4\", 2, 21),\n])\nprint(res25)  # >>> [2, 2, 2]\n\nres26 = r.ts().madd([\n        (\"rg:2\", 3, 1.9),\n        (\"rg:3\", 3, 0.81),\n        (\"rg:4\", 3, 19),\n])\nprint(res26)  # >>> [3, 3, 3]\n\nres27 = r.ts().madd([\n        (\"rg:2\", 4, 1.78),\n        (\"rg:3\", 4, 0.74),\n        (\"rg:4\", 4, 23),\n])\nprint(res27)  # >>> [4, 4, 4]\n\n# Retrieve the last data point from each US time series. If\n# you don't specify any labels, an empty array is returned\n# for the labels.\nres28 = r.ts().mget([\"location=us\"])\nprint(res28)  # >>> [{'rg:2': [{}, 4, 1.78]}, {'rg:3': [{}, 4, 0.74]}]\n\n# Retrieve the same data points, but include the `unit`\n# label in the results.\nres29 = r.ts().mget([\"location=us\"], select_labels=[\"unit\"])\nprint(res29)  # >>> [{'unit': 'cm'}, (4, 1.78), {'unit': 'in'}, (4, 0.74)]\n\n# Retrieve data points up to time 2 (inclusive) from all\n# time series that use millimeters as the unit. Include all\n# labels in the results.\nres30 = r.ts().mrange(\n    \"-\", 2, filters=[\"unit=mm\"], with_labels=True\n)\nprint(res30)\n# >>> [{'rg:4': [{'location': 'uk', 'unit': 'mm'}, [(0, 25.4),...\n\n# Retrieve data points from time 1 to time 3 (inclusive) from\n# all time series that use centimeters or millimeters as the unit,\n# but only return the `location` label. Return the results\n# in descending order of timestamp.\nres31 = r.ts().mrevrange(\n    1, 3, filters=[\"unit=(cm,mm)\"], select_labels=[\"location\"]\n)\nprint(res31)\n# >>> [[{'location': 'uk'}, (3, 19.0), (2, 21.0), (1, 18.0)],...","section_id":"query-multiple-time-series"},{"id":"aggregation-ex0","language":"plaintext","code":"> TS.RANGE rg:2 - + AGGREGATION avg 2\n1) 1) (integer) 0\n   2) 1.9500000000000002\n2) 1) (integer) 2\n   2) 2.0999999999999996\n3) 1) (integer) 4\n   2) 1.78","section_id":"aggregation"},{"id":"aggregation-ex1","language":"csharp","code":"IReadOnlyList<TimeSeriesTuple> res32 = db.TS().Range(\n            \"rg:2\", \"-\", \"+\",\n            aggregation: TsAggregation.Avg,\n            timeBucket: 2\n        );\n        Console.WriteLine($\"[{string.Join(\", \", res32.Select(t => $\"({t.Time.Value}, {t.Val})\"))}]\");\n        \/\/ >>> [(0, 1.95), (2, 2.1), (4, 1.78)]","section_id":"aggregation"},{"id":"aggregation-ex2","language":"go","code":"res32, err := rdb.TSRangeWithArgs(\n\t\tctx,\n\t\t\"rg:2\",\n\t\t0,\n\t\tmath.MaxInt64,\n\t\t&redis.TSRangeOptions{\n\t\t\tAggregator:     redis.Avg,\n\t\t\tBucketDuration: 2,\n\t\t},\n\t).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res32)\n\t\/\/ >>> [{0 1.9500000000000002} {2 2.0999999999999996} {4 1.78}]","section_id":"aggregation"},{"id":"aggregation-ex3","language":"java","code":"List<TSElement> res32 = jedis.tsRange(\"rg:2\",\n            TSRangeParams.rangeParams()\n                .fromTimestamp(0L)\n                .toTimestamp(4L)\n                .aggregation(AggregationType.AVG, 2)\n        );\n        System.out.println(res32);\n        \/\/ >>> [(0:1.9500000000000002), (2:2.0999999999999996), (4:1.78)]","section_id":"aggregation"},{"id":"aggregation-ex4","language":"javascript","code":"const res32 = await client.ts.range('rg:2', '-', '+', {\n  AGGREGATION: {\n    type: TIME_SERIES_AGGREGATION_TYPE.AVG,\n    timeBucket: 2\n  }\n});\nconsole.log(res32);\n\/\/ >>> [{ timestamp: 0, value: 1.9500000000000002 },{ timestamp: 2, value: 2.0999999999999996 }, { timestamp: 4, value: 1.78 }]","section_id":"aggregation"},{"id":"aggregation-ex5","language":"python","code":"res32 = r.ts().range(\n    \"rg:2\", \"-\", \"+\",\n    aggregation_type=\"avg\",\n    bucket_size_msec=2\n)\nprint(res32)\n# >>> [(0, 1.9500000000000002), (2, 2.0999999999999996), (4, 1.78)]","section_id":"aggregation"},{"id":"bucket-alignment-ex0","language":"plaintext","code":"> TS.CREATE sensor3\nOK\n> TS.MADD sensor3 10 1000 sensor3 20 2000 sensor3 30 3000 sensor3 40 4000 sensor3 50 5000 sensor3 60 6000 sensor3 70 7000\n1) (integer) 10\n2) (integer) 20\n3) (integer) 30\n4) (integer) 40\n5) (integer) 50\n6) (integer) 60\n7) (integer) 70\n> TS.RANGE sensor3 10 70 AGGREGATION min 25\n1) 1) (integer) 0\n   2) 1000\n2) 1) (integer) 25\n   2) 3000\n3) 1) (integer) 50\n   2) 5000","section_id":"bucket-alignment"},{"id":"bucket-alignment-ex1","language":"csharp","code":"bool res33 = db.TS().Create(\n            \"sensor3\",\n            new TsCreateParamsBuilder()\n                .build()\n        );\n        Console.WriteLine(res33); \/\/ >>> True\n\n        var sensorSequence = new List<(string, TimeStamp, double)>\n        {\n            (\"sensor3\", 10, 1000),\n            (\"sensor3\", 20, 2000),\n            (\"sensor3\", 30, 3000),\n            (\"sensor3\", 40, 4000),\n            (\"sensor3\", 50, 5000),\n            (\"sensor3\", 60, 6000),\n            (\"sensor3\", 70, 7000)\n        };\n        IReadOnlyList<TimeStamp> res34 = db.TS().MAdd(sensorSequence);\n        Console.WriteLine($\"[{string.Join(\", \", res34.Select(t => t.Value))}]\");\n        \/\/ >>> [10, 20, 30, 40, 50, 60, 70]\n\n        IReadOnlyList<TimeSeriesTuple> res35 = db.TS().Range(\n            \"sensor3\", 10, 70,\n            aggregation: TsAggregation.Min,\n            timeBucket: 25\n        );\n        Console.WriteLine($\"[{string.Join(\", \", res35.Select(t => $\"({t.Time.Value}, {t.Val})\"))}]\");\n        \/\/ >>> [(0, 1000), (25, 3000), (50, 5000)]","section_id":"bucket-alignment"},{"id":"bucket-alignment-ex2","language":"go","code":"res1, err := rdb.TSCreate(ctx, \"sensor3\").Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res1) \/\/ >>> OK\n\n\tres2, err := rdb.TSMAdd(ctx, [][]interface{}{\n\t\t{\"sensor3\", 10, 1000},\n\t\t{\"sensor3\", 20, 2000},\n\t\t{\"sensor3\", 30, 3000},\n\t\t{\"sensor3\", 40, 4000},\n\t\t{\"sensor3\", 50, 5000},\n\t\t{\"sensor3\", 60, 6000},\n\t\t{\"sensor3\", 70, 7000},\n\t}).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res2) \/\/ >>> [10 20 30 40 50 60 70]\n\n\tres3, err := rdb.TSRangeWithArgs(\n\t\tctx,\n\t\t\"sensor3\",\n\t\t10,\n\t\t70,\n\t\t&redis.TSRangeOptions{\n\t\t\tAggregator:     redis.Min,\n\t\t\tBucketDuration: 25,\n\t\t},\n\t).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res3) \/\/ >>> [{0 1000} {25 3000} {50 5000}]","section_id":"bucket-alignment"},{"id":"bucket-alignment-ex3","language":"java","code":"String res33 = jedis.tsCreate(\"sensor3\");\n        System.out.println(res33); \/\/ >>> OK\n\n        List<Long> res34 = jedis.tsMAdd(\n            new AbstractMap.SimpleEntry<>(\"sensor3\", new TSElement(10L, 1000.0)),\n            new AbstractMap.SimpleEntry<>(\"sensor3\", new TSElement(20L, 2000.0)),\n            new AbstractMap.SimpleEntry<>(\"sensor3\", new TSElement(30L, 3000.0)),\n            new AbstractMap.SimpleEntry<>(\"sensor3\", new TSElement(40L, 4000.0)),\n            new AbstractMap.SimpleEntry<>(\"sensor3\", new TSElement(50L, 5000.0)),\n            new AbstractMap.SimpleEntry<>(\"sensor3\", new TSElement(60L, 6000.0)),\n            new AbstractMap.SimpleEntry<>(\"sensor3\", new TSElement(70L, 7000.0))\n        );\n        System.out.println(res34); \/\/ >>> [10, 20, 30, 40, 50, 60, 70]\n\n        List<TSElement> res35 = jedis.tsRange(\"sensor3\",\n            TSRangeParams.rangeParams()\n                .fromTimestamp(10L)\n                .toTimestamp(70L)\n                .aggregation(AggregationType.MIN, 25)\n        );\n        System.out.println(res35);\n        \/\/ >>> [(0:1000.0), (25:3000.0), (50:5000.0)]","section_id":"bucket-alignment"},{"id":"bucket-alignment-ex4","language":"javascript","code":"const res33 = await client.ts.create('sensor3');\nconsole.log(res33); \/\/ >>> OK\n\nconst res34 = await client.ts.mAdd([\n  { key: 'sensor3', timestamp: 10, value: 1000 },\n  { key: 'sensor3', timestamp: 20, value: 2000 },\n  { key: 'sensor3', timestamp: 30, value: 3000 },\n  { key: 'sensor3', timestamp: 40, value: 4000 },\n  { key: 'sensor3', timestamp: 50, value: 5000 },\n  { key: 'sensor3', timestamp: 60, value: 6000 },\n  { key: 'sensor3', timestamp: 70, value: 7000 }\n]);\nconsole.log(res34); \/\/ >>> [10, 20, 30, 40, 50, 60, 70]\n\nconst res35 = await client.ts.range('sensor3', 10, 70, {\n  AGGREGATION: {\n    type: TIME_SERIES_AGGREGATION_TYPE.MIN,\n    timeBucket: 25\n  }\n});\nconsole.log(res35);\n\/\/ >>> [{ timestamp: 0, value: 1000 }, { timestamp: 25, value: 3000 }, { timestamp: 50, value: 5000 }]","section_id":"bucket-alignment"},{"id":"bucket-alignment-ex5","language":"python","code":"res33 = r.ts().create(\"sensor3\")\nprint(res33)  # >>> True\n\nres34 = r.ts().madd([\n    (\"sensor3\", 10, 1000),\n    (\"sensor3\", 20, 2000),\n    (\"sensor3\", 30, 3000),\n    (\"sensor3\", 40, 4000),\n    (\"sensor3\", 50, 5000),\n    (\"sensor3\", 60, 6000),\n    (\"sensor3\", 70, 7000),\n])\nprint(res34)  # >>> [10, 20, 30, 40, 50, 60, 70]\n\nres35 = r.ts().range(\n    \"sensor3\", 10, 70,\n    aggregation_type=\"min\",\n    bucket_size_msec=25\n)\nprint(res35)\n# >>> [(0, 1000.0), (25, 3000.0), (50, 5000.0)]","section_id":"bucket-alignment"},{"id":"bucket-alignment-ex6","language":"plaintext","code":"Value:        |      (1000)     (2000)     (3000)     (4000)     (5000)     (6000)     (7000)\nTimestamp:    |-------|10|-------|20|-------|30|-------|40|-------|50|-------|60|-------|70|--->\n\nBucket(25ms): |_________________________||_________________________||___________________________|\n                           V                          V                           V\n                  min(1000, 2000)=1000      min(3000, 4000)=3000     min(5000, 6000, 7000)=5000","section_id":"bucket-alignment"},{"id":"bucket-alignment-ex7","language":"plaintext","code":"> TS.RANGE sensor3 10 70 AGGREGATION min 25 ALIGN start\n1) 1) (integer) 10\n   2) 1000\n2) 1) (integer) 35\n   2) 4000\n3) 1) (integer) 60\n   2) 6000","section_id":"bucket-alignment"},{"id":"bucket-alignment-ex8","language":"csharp","code":"IReadOnlyList<TimeSeriesTuple> res36 = db.TS().Range(\n            \"sensor3\", 10, 70,\n            aggregation: TsAggregation.Min,\n            timeBucket: 25,\n            align: \"-\"\n        );\n        Console.WriteLine(\n            $\"[{string.Join(\", \", res36.Select(t => $\"({t.Time.Value}, {t.Val})\"))}]\"\n        );\n        \/\/ >>> [(10, 1000), (35, 4000), (60, 6000)]","section_id":"bucket-alignment"},{"id":"bucket-alignment-ex9","language":"go","code":"res4, err := rdb.TSRangeWithArgs(\n\t\tctx,\n\t\t\"sensor3\",\n\t\t10,\n\t\t70,\n\t\t&redis.TSRangeOptions{\n\t\t\tAggregator:     redis.Min,\n\t\t\tBucketDuration: 25,\n\t\t\tAlign:          \"START\",\n\t\t},\n\t).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res4) \/\/ >>> [{10 1000} {35 4000} {60 6000}]","section_id":"bucket-alignment"},{"id":"bucket-alignment-ex10","language":"java","code":"List<TSElement> res36 = jedis.tsRange(\"sensor3\",\n            TSRangeParams.rangeParams()\n                .fromTimestamp(10L)\n                .toTimestamp(70L)\n                .aggregation(AggregationType.MIN, 25)\n                .alignStart()\n        );\n        System.out.println(res36);\n        \/\/ >>> [(10:1000.0), (35:4000.0), (60:6000.0)]","section_id":"bucket-alignment"},{"id":"bucket-alignment-ex11","language":"javascript","code":"const res36 = await client.ts.range('sensor3', 10, 70, {\n  AGGREGATION: {\n    type: TIME_SERIES_AGGREGATION_TYPE.MIN,\n    timeBucket: 25\n  },\n  ALIGN: 'START'\n});\nconsole.log(res36);\n\/\/ >>> [{ timestamp: 10, value: 1000 }, { timestamp: 35, value: 4000 }, { timestamp: 60, value: 6000 }]","section_id":"bucket-alignment"},{"id":"bucket-alignment-ex12","language":"python","code":"res36 = r.ts().range(\n    \"sensor3\", 10, 70,\n    aggregation_type=\"min\",\n    bucket_size_msec=25,\n    align=\"START\"\n)\nprint(res36)\n# >>> [(10, 1000.0), (35, 4000.0), (60, 6000.0)]","section_id":"bucket-alignment"},{"id":"bucket-alignment-ex13","language":"plaintext","code":"Value:        |      (1000)     (2000)     (3000)     (4000)     (5000)     (6000)     (7000)\nTimestamp:    |-------|10|-------|20|-------|30|-------|40|-------|50|-------|60|-------|70|--->\n\nBucket(25ms):          |__________________________||_________________________||___________________________|\n                                    V                          V                           V\n                        min(1000, 2000, 3000)=1000      min(4000, 5000)=4000     min(6000, 7000)=6000","section_id":"bucket-alignment"},{"id":"aggregation-across-timeseries-ex0","language":"plaintext","code":"> TS.CREATE wind:1 LABELS country uk\nOK\n> TS.CREATE wind:2 LABELS country uk\nOK\n> TS.CREATE wind:3 LABELS country us\nOK\n> TS.CREATE wind:4 LABELS country us\nOK\n> TS.MADD wind:1 1 12 wind:2 1 18 wind:3 1 5 wind:4 1 20\n1) (integer) 1\n2) (integer) 1\n3) (integer) 1\n4) (integer) 1\n> TS.MADD wind:1 2 14 wind:2 2 21 wind:3 2 4 wind:4 2 25\n1) (integer) 2\n2) (integer) 2\n3) (integer) 2\n4) (integer) 2\n> TS.MADD wind:1 3 10 wind:2 3 24 wind:3 3 8 wind:4 3 18\n1) (integer) 3\n2) (integer) 3\n3) (integer) 3\n4) (integer) 3\n\n# The result pairs contain the timestamp and the maximum sample value\n# for the country at that timestamp.\n> TS.MRANGE - + FILTER country=(us,uk) GROUPBY country REDUCE max\n1) 1) \"country=uk\"\n   2) (empty array)\n   3) 1) 1) (integer) 1\n         2) 18\n      2) 1) (integer) 2\n         2) 21\n      3) 1) (integer) 3\n         2) 24\n2) 1) \"country=us\"\n   2) (empty array)\n   3) 1) 1) (integer) 1\n         2) 20\n      2) 1) (integer) 2\n         2) 25\n      3) 1) (integer) 3\n         2) 18\n\n# The result pairs contain the timestamp and the average sample value\n# for the country at that timestamp.\n> TS.MRANGE - + FILTER country=(us,uk) GROUPBY country REDUCE avg\n1) 1) \"country=uk\"\n   2) (empty array)\n   3) 1) 1) (integer) 1\n         2) 15\n      2) 1) (integer) 2\n         2) 17.5\n      3) 1) (integer) 3\n         2) 17\n2) 1) \"country=us\"\n   2) (empty array)\n   3) 1) 1) (integer) 1\n         2) 12.5\n      2) 1) (integer) 2\n         2) 14.5\n      3) 1) (integer) 3\n         2) 13","section_id":"aggregation-across-timeseries"},{"id":"aggregation-across-timeseries-ex1","language":"csharp","code":"var ukLabels = new List<TimeSeriesLabel> { new(\"country\", \"uk\") };\n\n        bool res37 = db.TS().Create(\n            \"wind:1\",\n            new TsCreateParamsBuilder()\n                .AddLabels(ukLabels)\n                .build()\n        );\n        Console.WriteLine(res37); \/\/ >>> True\n\n        bool res38 = db.TS().Create(\n            \"wind:2\",\n            new TsCreateParamsBuilder()\n                .AddLabels(ukLabels)\n                .build()\n        );\n        Console.WriteLine(res38); \/\/ >>> True\n\n        var usLabels = new List<TimeSeriesLabel> { new(\"country\", \"us\") };\n        bool res39 = db.TS().Create(\n            \"wind:3\",\n            new TsCreateParamsBuilder()\n                .AddLabels(usLabels)\n                .build()\n        );\n        Console.WriteLine(res39); \/\/ >>> True\n\n        bool res40 = db.TS().Create(\n            \"wind:4\",\n            new TsCreateParamsBuilder()\n                .AddLabels(usLabels)\n                .build()\n        );\n        Console.WriteLine(res40); \/\/ >>> True\n\n        var windSequence1 = new List<(string, TimeStamp, double)>\n        {\n            (\"wind:1\", 1, 12),\n            (\"wind:2\", 1, 18),\n            (\"wind:3\", 1, 5),\n            (\"wind:4\", 1, 20)\n        };\n        IReadOnlyList<TimeStamp> res41 = db.TS().MAdd(windSequence1);\n        Console.WriteLine(\n            $\"[{string.Join(\", \", res41.Select(t => t.Value))}]\"\n        );\n        \/\/ >>> [1, 1, 1, 1]\n\n        var windSequence2 = new List<(string, TimeStamp, double)>\n        {\n            (\"wind:1\", 2, 14),\n            (\"wind:2\", 2, 21),\n            (\"wind:3\", 2, 4),\n            (\"wind:4\", 2, 25)\n        };\n        IReadOnlyList<TimeStamp> res42 = db.TS().MAdd(windSequence2);\n        Console.WriteLine(\n            $\"[{string.Join(\", \", res42.Select(t => t.Value))}]\"\n        );\n        \/\/ >>> [2, 2, 2, 2]\n\n        var windSequence3 = new List<(string, TimeStamp, double)>\n        {\n            (\"wind:1\", 3, 10),\n            (\"wind:2\", 3, 24),\n            (\"wind:3\", 3, 8),\n            (\"wind:4\", 3, 18)\n        };\n        IReadOnlyList<TimeStamp> res43 = db.TS().MAdd(windSequence3);\n        Console.WriteLine(\n            $\"[{string.Join(\", \", res43.Select(t => t.Value))}]\"\n        );\n        \/\/ >>> [3, 3, 3, 3]\n\n        \/\/ The result pairs contain the timestamp and the maximum sample value\n        \/\/ for the country at that timestamp.\n        var countryFilters = new List<string> { \"country=(us,uk)\" };\n        IReadOnlyList<\n            (string, IReadOnlyList<TimeSeriesLabel>, IReadOnlyList<TimeSeriesTuple>)\n        > res44 = db.TS().MRange(\n            \"-\", \"+\",\n            countryFilters,\n            groupbyTuple: (\"country\", TsReduce.Max)\n        );\n        Console.WriteLine(res44.Count); \/\/ >>> 2\n\n        foreach (var (key, labelsResult, values) in res44)\n        {\n            Console.WriteLine($\"{key}:\");\n            Console.WriteLine($\"  Values: [{string.Join(\", \", values.Select(t => $\"({t.Time.Value}, {t.Val})\"))}]\");\n        }\n        \/\/ >>> country=uk\n        \/\/ >>>   Values: [(1, 18), (2, 21), (3, 24)]\n        \/\/ >>> country=us\n        \/\/ >>>   Values: [(1, 20), (2, 25), (3, 18)]\n\n        \/\/ The result pairs contain the timestamp and the average sample value\n        \/\/ for the country at that timestamp.\n        IReadOnlyList<\n            (string, IReadOnlyList<TimeSeriesLabel>, IReadOnlyList<TimeSeriesTuple>)\n        > res45 = db.TS().MRange(\n            \"-\", \"+\",\n            countryFilters,\n            groupbyTuple: (\"country\", TsReduce.Avg)\n        );\n        Console.WriteLine(res45.Count); \/\/ >>> 2\n\n        foreach (var (key, labelsResult, values) in res45)\n        {\n            Console.WriteLine($\"{key}:\");\n            Console.WriteLine($\"  Values: [{string.Join(\", \", values.Select(t => $\"({t.Time.Value}, {t.Val})\"))}]\");\n        }\n        \/\/ >>>   country=uk\n        \/\/ >>>      Values: [(1, 14), (2, 18), (3, 10)]\n        \/\/ >>>   country=us\n        \/\/ >>>      Values: [(1, 16), (2, 22), (3, 14)]","section_id":"aggregation-across-timeseries"},{"id":"aggregation-across-timeseries-ex2","language":"go","code":"res37, err := rdb.TSCreateWithArgs(ctx, \"wind:1\", &redis.TSOptions{\n\t\tLabels: map[string]string{\"country\": \"uk\"},\n\t}).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res37) \/\/ >>> OK\n\n\tres38, err := rdb.TSCreateWithArgs(ctx, \"wind:2\", &redis.TSOptions{\n\t\tLabels: map[string]string{\"country\": \"uk\"},\n\t}).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res38) \/\/ >>> OK\n\n\tres39, err := rdb.TSCreateWithArgs(ctx, \"wind:3\", &redis.TSOptions{\n\t\tLabels: map[string]string{\"country\": \"us\"},\n\t}).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res39) \/\/ >>> OK\n\n\tres40, err := rdb.TSCreateWithArgs(ctx, \"wind:4\", &redis.TSOptions{\n\t\tLabels: map[string]string{\"country\": \"us\"},\n\t}).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res40) \/\/ >>> OK\n\n\tres41, err := rdb.TSMAdd(ctx, [][]interface{}{\n\t\t{\"wind:1\", 1, 12},\n\t\t{\"wind:2\", 1, 18},\n\t\t{\"wind:3\", 1, 5},\n\t\t{\"wind:4\", 1, 20},\n\t}).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res41) \/\/ >>> [1 1 1 1]\n\n\tres42, err := rdb.TSMAdd(ctx, [][]interface{}{\n\t\t{\"wind:1\", 2, 14},\n\t\t{\"wind:2\", 2, 21},\n\t\t{\"wind:3\", 2, 4},\n\t\t{\"wind:4\", 2, 25},\n\t}).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res42) \/\/ >>> [2 2 2 2]\n\n\tres43, err := rdb.TSMAdd(ctx, [][]interface{}{\n\t\t{\"wind:1\", 3, 10},\n\t\t{\"wind:2\", 3, 24},\n\t\t{\"wind:3\", 3, 8},\n\t\t{\"wind:4\", 3, 18},\n\t}).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res43) \/\/ >>> [3 3 3 3]\n\n\t\/\/ The result pairs contain the timestamp and the maximum sample value\n\t\/\/ for the country at that timestamp.\n\tres44, err := rdb.TSMRangeWithArgs(\n\t\tctx,\n\t\t0,\n\t\tmath.MaxInt64,\n\t\t[]string{\"country=(us,uk)\"},\n\t\t&redis.TSMRangeOptions{\n\t\t\tGroupByLabel: \"country\",\n\t\t\tReducer:      \"max\",\n\t\t},\n\t).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tres44Keys := slices.Collect(maps.Keys(res44))\n\tsort.Strings(res44Keys)\n\n\tfor _, k := range res44Keys {\n\t\tlabels := res44[k][0].(map[interface{}]interface{})\n\t\tlabelKeys := make([]string, 0, len(labels))\n\n\t\tfor lk := range labels {\n\t\t\tlabelKeys = append(labelKeys, lk.(string))\n\t\t}\n\n\t\tsort.Strings(labelKeys)\n\n\t\tfmt.Printf(\"%v:\\n\", k)\n\n\t\tfor _, lk := range labelKeys {\n\t\t\tfmt.Printf(\"  %v: %v\\n\", lk, labels[lk])\n\t\t}\n\n\t\tfmt.Printf(\"  %v\\n\", res44[k][1])\n\t\tfmt.Printf(\"  %v\\n\", res44[k][2])\n\t\tfmt.Printf(\"  %v\\n\", res44[k][3])\n\t}\n\t\/\/ >>> country=uk:\n\t\/\/ >>>   map[reducers:[max]]\n\t\/\/ >>>   map[sources:[wind:1 wind:2]]\n\t\/\/ >>>   [[1 18] [2 21] [3 24]]\n\t\/\/ >>> country=us:\n\t\/\/ >>>   map[reducers:[max]]\n\t\/\/ >>>   map[sources:[wind:3 wind:4]]\n\t\/\/ >>>   [[1 20] [2 25] [3 18]]\n\n\t\/\/ The result pairs contain the timestamp and the average sample value\n\t\/\/ for the country at that timestamp.\n\tres45, err := rdb.TSMRangeWithArgs(\n\t\tctx,\n\t\t0,\n\t\tmath.MaxInt64,\n\t\t[]string{\"country=(us,uk)\"},\n\t\t&redis.TSMRangeOptions{\n\t\t\tGroupByLabel: \"country\",\n\t\t\tReducer:      \"avg\",\n\t\t},\n\t).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tres45Keys := slices.Collect(maps.Keys(res45))\n\tsort.Strings(res45Keys)\n\n\tfor _, k := range res45Keys {\n\t\tlabels := res45[k][0].(map[interface{}]interface{})\n\t\tlabelKeys := make([]string, 0, len(labels))\n\n\t\tfor lk := range labels {\n\t\t\tlabelKeys = append(labelKeys, lk.(string))\n\t\t}\n\n\t\tsort.Strings(labelKeys)\n\n\t\tfmt.Printf(\"%v:\\n\", k)\n\n\t\tfor _, lk := range labelKeys {\n\t\t\tfmt.Printf(\"  %v: %v\\n\", lk, labels[lk])\n\t\t}\n\n\t\tfmt.Printf(\"  %v\\n\", res45[k][1])\n\t\tfmt.Printf(\"  %v\\n\", res45[k][2])\n\t\tfmt.Printf(\"  %v\\n\", res45[k][3])\n\t}\n\t\/\/ >>> country=uk:\n\t\/\/ >>>   map[reducers:[avg]]\n\t\/\/ >>>   map[sources:[wind:1 wind:2]]\n\t\/\/ >>>   [[1 15] [2 17.5] [3 17]]\n\t\/\/ >>> country=us:\n\t\/\/ >>>   map[reducers:[avg]]\n\t\/\/ >>>   map[sources:[wind:3 wind:4]]\n\t\/\/ >>>   [[1 12.5] [2 14.5] [3 13]]","section_id":"aggregation-across-timeseries"},{"id":"aggregation-across-timeseries-ex3","language":"java","code":"Map<String, String> ukCountry = new HashMap<>();\n        ukCountry.put(\"country\", \"uk\");\n        \n        Map<String, String> usCountry = new HashMap<>();\n        usCountry.put(\"country\", \"us\");\n\n        jedis.tsCreate(\"wind:1\", TSCreateParams.createParams().labels(ukCountry));\n        jedis.tsCreate(\"wind:2\", TSCreateParams.createParams().labels(ukCountry));\n        jedis.tsCreate(\"wind:3\", TSCreateParams.createParams().labels(usCountry));\n        jedis.tsCreate(\"wind:4\", TSCreateParams.createParams().labels(usCountry));\n\n        jedis.tsMAdd(\n            new AbstractMap.SimpleEntry<>(\"wind:1\", new TSElement(0L, 10.0)),\n            new AbstractMap.SimpleEntry<>(\"wind:2\", new TSElement(0L, 12.0)),\n            new AbstractMap.SimpleEntry<>(\"wind:3\", new TSElement(0L, 8.0)),\n            new AbstractMap.SimpleEntry<>(\"wind:4\", new TSElement(0L, 15.0))\n        );\n\n        jedis.tsMAdd(\n            new AbstractMap.SimpleEntry<>(\"wind:1\", new TSElement(1L, 11.0)),\n            new AbstractMap.SimpleEntry<>(\"wind:2\", new TSElement(1L, 13.0)),\n            new AbstractMap.SimpleEntry<>(\"wind:3\", new TSElement(1L, 9.0)),\n            new AbstractMap.SimpleEntry<>(\"wind:4\", new TSElement(1L, 16.0))\n        );\n\n        jedis.tsMAdd(\n            new AbstractMap.SimpleEntry<>(\"wind:1\", new TSElement(2L, 9.0)),\n            new AbstractMap.SimpleEntry<>(\"wind:2\", new TSElement(2L, 11.0)),\n            new AbstractMap.SimpleEntry<>(\"wind:3\", new TSElement(2L, 7.0)),\n            new AbstractMap.SimpleEntry<>(\"wind:4\", new TSElement(2L, 14.0))\n        );\n\n        jedis.tsMAdd(\n            new AbstractMap.SimpleEntry<>(\"wind:1\", new TSElement(3L, 12.0)),\n            new AbstractMap.SimpleEntry<>(\"wind:2\", new TSElement(3L, 14.0)),\n            new AbstractMap.SimpleEntry<>(\"wind:3\", new TSElement(3L, 10.0)),\n            new AbstractMap.SimpleEntry<>(\"wind:4\", new TSElement(3L, 17.0))\n        );\n\n        jedis.tsMAdd(\n            new AbstractMap.SimpleEntry<>(\"wind:1\", new TSElement(4L, 8.0)),\n            new AbstractMap.SimpleEntry<>(\"wind:2\", new TSElement(4L, 10.0)),\n            new AbstractMap.SimpleEntry<>(\"wind:3\", new TSElement(4L, 6.0)),\n            new AbstractMap.SimpleEntry<>(\"wind:4\", new TSElement(4L, 13.0))\n        );\n\n        \/\/ Group by country with max reduction\n        Map<String, TSMRangeElements> res44 = jedis.tsMRange(\n            TSMRangeParams.multiRangeParams(0L, 4L)\n                .filter(\"country=(us,uk)\")\n                .groupBy(\"country\", \"max\"));\n        System.out.println(res44);\n        \/\/ >>> {country=uk=TSMRangeElements{key=country=uk, labels={}, value=[(0:12.0)...\n\n        \/\/ Group by country with avg reduction\n        Map<String, TSMRangeElements> res45 = jedis.tsMRange(\n            TSMRangeParams.multiRangeParams(0L, 4L)\n                .filter(\"country=(us,uk)\")\n                .groupBy(\"country\", \"avg\"));\n        System.out.println(res45);\n        \/\/ >>> {country=uk=TSMRangeElements{key=country=uk, labels={}, value=[(0:11.0)...","section_id":"aggregation-across-timeseries"},{"id":"aggregation-across-timeseries-ex4","language":"javascript","code":"const res37 = await client.ts.create('wind:1', {\n  LABELS: { country: 'uk' }\n});\nconsole.log(res37); \/\/ >>> OK\n\nconst res38 = await client.ts.create('wind:2', {\n  LABELS: { country: 'uk' }\n});\nconsole.log(res38); \/\/ >>> OK\n\nconst res39 = await client.ts.create('wind:3', {\n  LABELS: { country: 'us' }\n});\nconsole.log(res39); \/\/ >>> OK\n\nconst res40 = await client.ts.create('wind:4', {\n  LABELS: { country: 'us' }\n});\nconsole.log(res40); \/\/ >>> OK\n\nconst res41 = await client.ts.mAdd([\n  { key: 'wind:1', timestamp: 1, value: 12 },\n  { key: 'wind:2', timestamp: 1, value: 18 },\n  { key: 'wind:3', timestamp: 1, value: 5 },\n  { key: 'wind:4', timestamp: 1, value: 20 }\n]);\nconsole.log(res41); \/\/ >>> [1, 1, 1, 1]\n\nconst res42 = await client.ts.mAdd([\n  { key: 'wind:1', timestamp: 2, value: 14 },\n  { key: 'wind:2', timestamp: 2, value: 21 },\n  { key: 'wind:3', timestamp: 2, value: 4 },\n  { key: 'wind:4', timestamp: 2, value: 25 }\n]);\nconsole.log(res42); \/\/ >>> [2, 2, 2, 2]\n\nconst res43 = await client.ts.mAdd([\n  { key: 'wind:1', timestamp: 3, value: 10 },\n  { key: 'wind:2', timestamp: 3, value: 24 },\n  { key: 'wind:3', timestamp: 3, value: 8 },\n  { key: 'wind:4', timestamp: 3, value: 18 }\n]);\nconsole.log(res43); \/\/ >>> [3, 3, 3, 3]\n\n\/\/ The result pairs contain the timestamp and the maximum sample value\n\/\/ for the country at that timestamp.\nconst res44 = await client.ts.mRangeGroupBy(\n  '-', '+', ['country=(us,uk)'],\n  {label: 'country', REDUCE: TIME_SERIES_REDUCERS.MAX}\n);\nconsole.log(res44);\n\/\/ >>> { \"country=uk\": { samples: [\n\/\/   { timestamp: 1, value: 18 },\n\/\/   { timestamp: 2, value: 21 },\n\/\/   { timestamp: 3, value: 24 }\n\/\/ ] }, \"country=us\": { samples: [\n\/\/   { timestamp: 1, value: 20 },\n\/\/   { timestamp: 2, value: 25 },\n\/\/   { timestamp: 3, value: 18 }\n\/\/ ] } }\n\n\/\/ The result pairs contain the timestamp and the average sample value\n\/\/ for the country at that timestamp.\nconst res45 = await client.ts.mRangeGroupBy(\n  '-', '+', ['country=(us,uk)'],\n  { label: 'country', REDUCE: TIME_SERIES_REDUCERS.AVG}\n);\nconsole.log(res45);\n\/\/ >>> {\n\/\/ \"country=uk\": {\n\/\/   samples: [{ timestamp: 1, value: 15 }, { timestamp: 2, value: 17.5 }, { timestamp: 3, value: 17 }]\n\/\/ },\n\/\/ \"country=us\": {\n\/\/   samples: [{ timestamp: 1, value: 12.5 }, { timestamp: 2, value: 14.5 }, { timestamp: 3, value: 13 }]\n\/\/ }\n\/\/ }","section_id":"aggregation-across-timeseries"},{"id":"aggregation-across-timeseries-ex5","language":"python","code":"res37 = r.ts().create(\n    \"wind:1\",\n    labels={\"country\": \"uk\"}\n)\nprint(res37)  # >>> True\n\nres38 = r.ts().create(\n    \"wind:2\",\n    labels={\"country\": \"uk\"}\n)\nprint(res38)  # >>> True\n\nres39 = r.ts().create(\n    \"wind:3\",\n    labels={\"country\": \"us\"}\n)\nprint(res39)  # >>> True\n\nres40 = r.ts().create(\n    \"wind:4\",\n    labels={\"country\": \"us\"}\n)\nprint(res40)  # >>> True\n\nres41 = r.ts().madd([\n        (\"wind:1\", 1, 12),\n        (\"wind:2\", 1, 18),\n        (\"wind:3\", 1, 5),\n        (\"wind:4\", 1, 20),\n])\nprint(res41)  # >>> [1, 1, 1, 1]\n\nres42 = r.ts().madd([\n        (\"wind:1\", 2, 14),\n        (\"wind:2\", 2, 21),\n        (\"wind:3\", 2, 4),\n        (\"wind:4\", 2, 25),\n])\nprint(res42)  # >>> [2, 2, 2, 2]\n\nres43 = r.ts().madd([\n        (\"wind:1\", 3, 10),\n        (\"wind:2\", 3, 24),\n        (\"wind:3\", 3, 8),\n        (\"wind:4\", 3, 18),\n])\nprint(res43)  # >>> [3, 3, 3, 3]\n\n# The result pairs contain the timestamp and the maximum sample value\n# for the country at that timestamp.\nres44 = r.ts().mrange(\n    \"-\", \"+\",\n    filters=[\"country=(us,uk)\"],\n    groupby=\"country\",\n    reduce=\"max\"\n)\nprint(res44)\n# >>> [{'country=uk': [{}, [(1, 18.0), (2, 21.0), (3, 24.0)]]}, ...\n\n# The result pairs contain the timestamp and the average sample value\n# for the country at that timestamp.\nres45 = r.ts().mrange(\n    \"-\", \"+\",\n    filters=[\"country=(us,uk)\"],\n    groupby=\"country\",\n    reduce=\"avg\"\n)\nprint(res45)\n# >>> [{'country=uk': [{}, [(1, 15.0), (2, 17.5), (3, 17.0)]]}, ...","section_id":"aggregation-across-timeseries"},{"id":"nan-behavior-ex0","language":"bash","code":"# Create a temperature sensor time series\n> TS.CREATE sensor:temp LABELS type temperature location outdoor\n\n# Add normal readings and NaN for sensor malfunction\n> TS.MADD sensor:temp 1000 25.5 sensor:temp 1010 26.1 sensor:temp 1020 NaN sensor:temp 1030 24.8\n1) (integer) 1000\n2) (integer) 1010\n3) (integer) 1020\n4) (integer) 1030\n\n# Query all values - NaN is included in raw results\n> TS.RANGE sensor:temp - +\n1) 1) (integer) 1000\n   2) 25.5\n2) 1) (integer) 1010\n   2) 26.1\n3) 1) (integer) 1020\n   2) NaN\n4) 1) (integer) 1030\n   2) 24.8\n\n# Aggregate ignores NaN - average of 25.5, 26.1, 24.8 = 25.47\n> TS.RANGE sensor:temp - + AGGREGATION avg 1000\n1) 1) (integer) 1000\n   2) 25.466666666666665\n\n# Count non-NaN values\n> TS.RANGE sensor:temp - + AGGREGATION count 1000\n1) 1) (integer) 1000\n   2) 3\n\n# Count NaN values\n> TS.RANGE sensor:temp - + AGGREGATION countNaN 1000\n1) 1) (integer) 1000\n   2) 1\n\n# Count all values\n> TS.RANGE sensor:temp - + AGGREGATION countAll 1000\n1) 1) (integer) 1000\n   2) 4","section_id":"nan-behavior"},{"id":"compaction-ex0","language":"plaintext","code":"# The source time series.\n> TS.CREATE hyg:1\nOK\n# The destination time series for the compacted data.\n> TS.CREATE hyg:compacted\nOK\n# The compaction rule.\n> TS.CREATERULE hyg:1 hyg:compacted AGGREGATION min 3\nOK\n> TS.INFO hyg:1\n    .\n    .\n23) rules\n24) 1) 1) \"hyg:compacted\"\n       2) (integer) 3\n       3) MIN\n       4) (integer) 0\n    .\n    .\n> TS.INFO hyg:compacted\n    .\n    .\n21) sourceKey\n22) \"hyg:1\"\n    .\n    .","section_id":"compaction"},{"id":"compaction-ex1","language":"csharp","code":"bool res46 = db.TS().Create(\n            \"hyg:1\",\n            new TsCreateParamsBuilder().build()\n        );\n        Console.WriteLine(res46); \/\/ >>> True\n\n        bool res47 = db.TS().Create(\n            \"hyg:compacted\",\n            new TsCreateParamsBuilder().build()\n        );\n        Console.WriteLine(res47); \/\/ >>> True\n\n        var compactionRule = new TimeSeriesRule(\"hyg:compacted\", 3, TsAggregation.Min);\n        bool res48 = db.TS().CreateRule(\"hyg:1\", compactionRule);\n        Console.WriteLine(res48); \/\/ >>> True\n\n        TimeSeriesInformation res49 = db.TS().Info(\"hyg:1\");\n        Console.WriteLine(res49.Rules!.Count);\n        \/\/ >>> 1\n\n        TimeSeriesInformation res50 = db.TS().Info(\"hyg:compacted\");\n        Console.WriteLine(res50.SourceKey);\n        \/\/ >>> hyg:1","section_id":"compaction"},{"id":"compaction-ex2","language":"go","code":"res45, err := rdb.TSCreate(ctx, \"hyg:1\").Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res45) \/\/ >>> OK\n\n\tres46, err := rdb.TSCreate(ctx, \"hyg:compacted\").Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res46) \/\/ >>> OK\n\n\tres47, err := rdb.TSCreateRule(\n\t\tctx, \"hyg:1\", \"hyg:compacted\", redis.Min, 3,\n\t).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res47) \/\/ >>> OK\n\n\tres48, err := rdb.TSInfo(ctx, \"hyg:1\").Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res48[\"rules\"]) \/\/ >>> [[hyg:compacted 3 MIN 0]]\n\n\tres49, err := rdb.TSInfo(ctx, \"hyg:compacted\").Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res49[\"sourceKey\"]) \/\/ >>> hyg:1","section_id":"compaction"},{"id":"compaction-ex3","language":"java","code":"String res46 = jedis.tsCreate(\"hyg:1\");\n        System.out.println(res46); \/\/ >>> OK\n\n        String res47 = jedis.tsCreate(\"hyg:compacted\");\n        System.out.println(res47); \/\/ >>> OK\n\n        String res48 = jedis.tsCreateRule(\"hyg:1\", \"hyg:compacted\", AggregationType.MIN, 3);\n        System.out.println(res48); \/\/ >>> OK\n\n        TSInfo res49 = jedis.tsInfo(\"hyg:1\");\n        System.out.println(\"Rules: \" + res49.getProperty(\"rules\"));\n        \/\/ >>> Rules: [{compactionKey=hyg:compacted, bucketDuration=3, aggregationType=MIN, alignmentTimestamp=0}]\n\n        TSInfo res50 = jedis.tsInfo(\"hyg:compacted\");\n        System.out.println(\"Source key: \" + res50.getProperty(\"sourceKey\"));\n        \/\/ >>> Source key: hyg:1","section_id":"compaction"},{"id":"compaction-ex4","language":"javascript","code":"const res46 = await client.ts.create('hyg:1');\nconsole.log(res46); \/\/ >>> OK\n\nconst res47 = await client.ts.create('hyg:compacted');\nconsole.log(res47); \/\/ >>> OK\n\nconst res48 = await client.ts.createRule('hyg:1', 'hyg:compacted', TIME_SERIES_AGGREGATION_TYPE.MIN, 3);\nconsole.log(res48); \/\/ >>> OK\n\nconst res49 = await client.ts.info('hyg:1');\nconsole.log(res49.rules);\n\/\/ >>> [{ aggregationType: 'MIN', key: 'hyg:compacted', timeBucket: 3}]\n\nconst res50 = await client.ts.info('hyg:compacted');\nconsole.log(res50.sourceKey); \/\/ >>> 'hyg:1'","section_id":"compaction"},{"id":"compaction-ex5","language":"python","code":"res45 = r.ts().create(\"hyg:1\")\nprint(res45)  # >>> True\n\nres46 = r.ts().create(\"hyg:compacted\")\nprint(res46)  # >>> True\n\nres47 = r.ts().createrule(\"hyg:1\", \"hyg:compacted\", \"min\", 3)\nprint(res47)  # >>> True\n\nres48 = r.ts().info(\"hyg:1\")\nprint(res48.rules)\n# >>> [['hyg:compacted', 3, 'MIN', 0]]\n\nres49 = r.ts().info(\"hyg:compacted\")\nprint(res49.source_key)  # >>> 'hyg:1'","section_id":"compaction"},{"id":"compaction-ex6","language":"plaintext","code":"> TS.MADD hyg:1 0 75 hyg:1 1 77 hyg:1 2 78\n1) (integer) 0\n2) (integer) 1\n3) (integer) 2\n> ts.range hyg:compacted - +\n(empty array)\n> TS.ADD hyg:1 3 79\n(integer) 3\n> ts.range hyg:compacted - +\n1) 1) (integer) 0\n   2) 75","section_id":"compaction"},{"id":"compaction-ex7","language":"csharp","code":"var hygSequence1 = new List<(string, TimeStamp, double)>\n        {\n            (\"hyg:1\", 0, 75),\n            (\"hyg:1\", 1, 77),\n            (\"hyg:1\", 2, 78)\n        };\n        IReadOnlyList<TimeStamp> res51 = db.TS().MAdd(hygSequence1);\n        Console.WriteLine($\"[{string.Join(\", \", res51.Select(t => t.Value))}]\");\n        \/\/ >>> [0, 1, 2]\n\n        IReadOnlyList<TimeSeriesTuple> res52 = db.TS().Range(\"hyg:compacted\", \"-\", \"+\");\n        Console.WriteLine(res52.Count); \/\/ >>> 0\n\n        TimeStamp res53 = db.TS().Add(\n            \"hyg:1\",\n            new TsAddParamsBuilder()\n                .AddTimestamp(3)\n                .AddValue(79)\n                .build()\n        );\n        Console.WriteLine(res53.Value); \/\/ >>> 3\n\n        IReadOnlyList<TimeSeriesTuple> res54 = db.TS().Range(\"hyg:compacted\", \"-\", \"+\");\n        Console.WriteLine(\n            $\"[{string.Join(\", \", res54.Select(t => $\"({t.Time.Value}, {t.Val})\"))}]\"\n        );\n        \/\/ >>> [(0, 75)]","section_id":"compaction"},{"id":"compaction-ex8","language":"go","code":"res50, err := rdb.TSMAdd(ctx, [][]interface{}{\n\t\t{\"hyg:1\", 0, 75},\n\t\t{\"hyg:1\", 1, 77},\n\t\t{\"hyg:1\", 2, 78},\n\t}).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res50) \/\/ >>> [0 1 2]\n\n\tres51, err := rdb.TSRange(\n\t\tctx, \"hyg:compacted\", 0, math.MaxInt64,\n\t).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res51) \/\/ >>> []\n\n\tres52, err := rdb.TSAdd(ctx, \"hyg:1\", 3, 79).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res52) \/\/ >>> 3\n\n\tres53, err := rdb.TSRange(\n\t\tctx, \"hyg:compacted\", 0, math.MaxInt64,\n\t).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res53) \/\/ >>> [{0 75}]","section_id":"compaction"},{"id":"compaction-ex9","language":"java","code":"List<Long> res51 = jedis.tsMAdd(\n            new AbstractMap.SimpleEntry<>(\"hyg:1\", new TSElement(0L, 75.0)),\n            new AbstractMap.SimpleEntry<>(\"hyg:1\", new TSElement(1L, 77.0)),\n            new AbstractMap.SimpleEntry<>(\"hyg:1\", new TSElement(2L, 78.0))\n        );\n        System.out.println(res51); \/\/ >>> [0, 1, 2]\n\n        List<TSElement> res52 = jedis.tsRange(\"hyg:compacted\", 0L, 10L);\n        System.out.println(res52); \/\/ >>> []\n\n        long res53 = jedis.tsAdd(\"hyg:1\", 3L, 79.0);\n        System.out.println(res53); \/\/ >>> 3\n\n        List<TSElement> res54 = jedis.tsRange(\"hyg:compacted\", 0L, 10L);\n        System.out.println(res54); \/\/ >>> [(0:75.0)]","section_id":"compaction"},{"id":"compaction-ex10","language":"javascript","code":"const res51 = await client.ts.mAdd([\n  { key: 'hyg:1', timestamp: 0, value: 75 },\n  { key: 'hyg:1', timestamp: 1, value: 77 },\n  { key: 'hyg:1', timestamp: 2, value: 78 }\n]);\nconsole.log(res51); \/\/ >>> [0, 1, 2]\n\nconst res52 = await client.ts.range('hyg:compacted', '-', '+');\nconsole.log(res52); \/\/ >>> []\n\nconst res53 = await client.ts.add('hyg:1', 3, 79);\nconsole.log(res53); \/\/ >>> 3\n\nconst res54 = await client.ts.range('hyg:compacted', '-', '+');\nconsole.log(res54); \/\/ >>> [{ timestamp: 0, value: 75 }]","section_id":"compaction"},{"id":"compaction-ex11","language":"python","code":"res50 = r.ts().madd([\n    (\"hyg:1\", 0, 75),\n    (\"hyg:1\", 1, 77),\n    (\"hyg:1\", 2, 78),\n])\nprint(res50)  # >>> [0, 1, 2]\n\nres51 = r.ts().range(\"hyg:compacted\", \"-\", \"+\")\nprint(res51)  # >>> []\n\nres52 = r.ts().add(\"hyg:1\", 3, 79)\nprint(res52)  # >>> 3\n\nres53 = r.ts().range(\"hyg:compacted\", \"-\", \"+\")\nprint(res53)  # >>> [(0, 75.0)]","section_id":"compaction"},{"id":"delete-data-points-ex0","language":"plaintext","code":"> TS.INFO thermometer:1\n 1) totalSamples\n 2) (integer) 2\n 3) memoryUsage\n 4) (integer) 4856\n 5) firstTimestamp\n 6) (integer) 1\n 7) lastTimestamp\n 8) (integer) 2\n    .\n    .\n> TS.ADD thermometer:1 3 9.7\n(integer) 3\n> TS.INFO thermometer:1\n 1) totalSamples\n 2) (integer) 3\n 3) memoryUsage\n 4) (integer) 4856\n 5) firstTimestamp\n 6) (integer) 1\n 7) lastTimestamp\n 8) (integer) 3\n    .\n    .\n> TS.DEL thermometer:1 1 2\n(integer) 2\n> TS.INFO thermometer:1\n 1) totalSamples\n 2) (integer) 1\n 3) memoryUsage\n 4) (integer) 4856\n 5) firstTimestamp\n 6) (integer) 3\n 7) lastTimestamp\n 8) (integer) 3\n    .\n    .\n> TS.DEL thermometer:1 3 3\n(integer) 1\n> TS.INFO thermometer:1\n 1) totalSamples\n 2) (integer) 0\n    .\n    .","section_id":"delete-data-points"},{"id":"delete-data-points-ex1","language":"csharp","code":"TimeSeriesInformation res55 = db.TS().Info(\"thermometer:1\");\n        Console.WriteLine(res55.TotalSamples); \/\/ >>> 2\n        Console.WriteLine(res55.FirstTimeStamp!); \/\/ >>> 1\n        Console.WriteLine(res55.LastTimeStamp!); \/\/ >>> 2\n\n        TimeStamp res56 = db.TS().Add(\n            \"thermometer:1\",\n            new TsAddParamsBuilder()\n                .AddTimestamp(3)\n                .AddValue(9.7)\n                .build()\n        );\n        Console.WriteLine(res56.Value); \/\/ >>> 3\n\n        TimeSeriesInformation res57 = db.TS().Info(\"thermometer:1\");\n        Console.WriteLine(res57.TotalSamples); \/\/ >>> 3\n        Console.WriteLine(res57.FirstTimeStamp!); \/\/ >>> 1\n        Console.WriteLine(res57.LastTimeStamp!); \/\/ >>> 3\n\n        long res58 = db.TS().Del(\"thermometer:1\", 1, 2);\n        Console.WriteLine(res58); \/\/ >>> 2\n\n        TimeSeriesInformation res59 = db.TS().Info(\"thermometer:1\");\n        Console.WriteLine(res59.TotalSamples); \/\/ >>> 1\n        Console.WriteLine(res59.FirstTimeStamp!); \/\/ >>> 3\n        Console.WriteLine(res59.LastTimeStamp!); \/\/ >>> 3\n\n        long res60 = db.TS().Del(\"thermometer:1\", 3, 3);\n        Console.WriteLine(res60); \/\/ >>> 1\n\n        TimeSeriesInformation res61 = db.TS().Info(\"thermometer:1\");\n        Console.WriteLine(res61.TotalSamples); \/\/ >>> 0","section_id":"delete-data-points"},{"id":"delete-data-points-ex2","language":"go","code":"res54, err := rdb.TSInfo(ctx, \"thermometer:1\").Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res54[\"totalSamples\"])   \/\/ >>> 2\n\tfmt.Println(res54[\"firstTimestamp\"]) \/\/ >>> 1\n\tfmt.Println(res54[\"lastTimestamp\"])  \/\/ >>> 2\n\n\tres55, err := rdb.TSAdd(ctx, \"thermometer:1\", 3, 9.7).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res55) \/\/ >>> 3\n\n\tres56, err := rdb.TSInfo(ctx, \"thermometer:1\").Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res56[\"totalSamples\"])   \/\/ >>> 3\n\tfmt.Println(res56[\"firstTimestamp\"]) \/\/ >>> 1\n\tfmt.Println(res56[\"lastTimestamp\"])  \/\/ >>> 3\n\n\tres57, err := rdb.TSDel(ctx, \"thermometer:1\", 1, 2).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res57) \/\/ >>> 2\n\n\tres58, err := rdb.TSInfo(ctx, \"thermometer:1\").Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res58[\"totalSamples\"])   \/\/ >>> 1\n\tfmt.Println(res58[\"firstTimestamp\"]) \/\/ >>> 3\n\tfmt.Println(res58[\"lastTimestamp\"])  \/\/ >>> 3\n\n\tres59, err := rdb.TSDel(ctx, \"thermometer:1\", 3, 3).Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res59) \/\/ >>> 1\n\n\tres60, err := rdb.TSInfo(ctx, \"thermometer:1\").Result()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(res60[\"totalSamples\"]) \/\/ >>> 0","section_id":"delete-data-points"},{"id":"delete-data-points-ex3","language":"java","code":"TSInfo res55 = jedis.tsInfo(\"thermometer:1\");\n        System.out.println(res55.getProperty(\"totalSamples\")); \/\/ >>> 2\n        System.out.println(res55.getProperty(\"firstTimestamp\")); \/\/ >>> 1\n        System.out.println(res55.getProperty(\"lastTimestamp\")); \/\/ >>> 2\n\n        long res56 = jedis.tsAdd(\"thermometer:1\", 3L, 9.7);\n        System.out.println(res56); \/\/ >>> 3\n\n        TSInfo res57 = jedis.tsInfo(\"thermometer:1\");\n        System.out.println(res57.getProperty(\"totalSamples\")); \/\/ >>> 3\n\n        long res58 = jedis.tsDel(\"thermometer:1\", 1L, 2L);\n        System.out.println(res58); \/\/ >>> 2\n\n        TSInfo res59 = jedis.tsInfo(\"thermometer:1\");\n        System.out.println(res59.getProperty(\"totalSamples\")); \/\/ >>> 1\n\n        long res60 = jedis.tsDel(\"thermometer:1\", 3L, 3L);\n        System.out.println(res60); \/\/ >>> 1\n\n        TSInfo res61 = jedis.tsInfo(\"thermometer:1\");\n        System.out.println(res61.getProperty(\"totalSamples\")); \/\/ >>> 0","section_id":"delete-data-points"},{"id":"delete-data-points-ex4","language":"javascript","code":"const res55 = await client.ts.info('thermometer:1');\nconsole.log(res55.totalSamples); \/\/ >>> 2\nconsole.log(res55.firstTimestamp); \/\/ >>> 1\nconsole.log(res55.lastTimestamp); \/\/ >>> 2\n\nconst res56 = await client.ts.add('thermometer:1', 3, 9.7);\nconsole.log(res56); \/\/ >>> 3\n\nconst res57 = await client.ts.info('thermometer:1');\nconsole.log(res57.totalSamples); \/\/ >>> 3\nconsole.log(res57.firstTimestamp); \/\/ >>> 1\nconsole.log(res57.lastTimestamp); \/\/ >>> 3\n\nconst res58 = await client.ts.del('thermometer:1', 1, 2);\nconsole.log(res58); \/\/ >>> 2\n\nconst res59 = await client.ts.info('thermometer:1');\nconsole.log(res59.totalSamples); \/\/ >>> 1\nconsole.log(res59.firstTimestamp); \/\/ >>> 3\nconsole.log(res59.lastTimestamp); \/\/ >>> 3\n\nconst res60 = await client.ts.del('thermometer:1', 3, 3);\nconsole.log(res60); \/\/ >>> 1\n\nconst res61 = await client.ts.info('thermometer:1');\nconsole.log(res61.totalSamples); \/\/ >>> 0","section_id":"delete-data-points"},{"id":"delete-data-points-ex5","language":"python","code":"res54 = r.ts().info(\"thermometer:1\")\nprint(res54.total_samples)  # >>> 2\nprint(res54.first_timestamp)  # >>> 1\nprint(res54.last_timestamp)  # >>> 2\n\nres55 = r.ts().add(\"thermometer:1\", 3, 9.7)\nprint(res55)  # >>> 3\n\nres56 = r.ts().info(\"thermometer:1\")\nprint(res56.total_samples)  # >>> 3\nprint(res56.first_timestamp)  # >>> 1\nprint(res56.last_timestamp)  # >>> 3\n\nres57 = r.ts().delete(\"thermometer:1\", 1, 2)\nprint(res57)  # >>> 2\n\nres58 = r.ts().info(\"thermometer:1\")\nprint(res58.total_samples)  # >>> 1\nprint(res58.first_timestamp)  # >>> 3\nprint(res58.last_timestamp)  # >>> 3\n\nres59 = r.ts().delete(\"thermometer:1\", 3, 3)\nprint(res59)  # >>> 1\n\nres60 = r.ts().info(\"thermometer:1\")\nprint(res60.total_samples)  # >>> 0","section_id":"delete-data-points"}]}