From 7a681d32d437cceb2cb1890b2c093c59d970299e Mon Sep 17 00:00:00 2001 From: Andy Stark Date: Tue, 22 Jul 2025 14:38:11 +0100 Subject: [PATCH 1/5] DOC-5472 added and fixed tests up to --- doctests/timeseries_tut_test.go | 918 ++++++++++++++++++++++++++++++++ 1 file changed, 918 insertions(+) create mode 100644 doctests/timeseries_tut_test.go diff --git a/doctests/timeseries_tut_test.go b/doctests/timeseries_tut_test.go new file mode 100644 index 000000000..45bf9448e --- /dev/null +++ b/doctests/timeseries_tut_test.go @@ -0,0 +1,918 @@ +// EXAMPLE: time_series_tutorial +// HIDE_START +package example_commands_test + +import ( + "context" + "fmt" + "maps" + "math" + "slices" + "sort" + + "github.com/redis/go-redis/v9" +) + +// HIDE_END + +func ExampleClient_timeseries_create() { + ctx := context.Background() + + rdb := redis.NewClient(&redis.Options{ + Addr: "localhost:6379", + Password: "", // no password set + DB: 0, // use default DB + }) + + // REMOVE_START + // make sure we are working with fresh database + rdb.FlushDB(ctx) + rdb.Del(ctx, "thermometer:1", "thermometer:2", "thermometer:3") + // REMOVE_END + + // STEP_START create + res1, err := rdb.TSCreate(ctx, "thermometer:1").Result() + + if err != nil { + panic(err) + } + + fmt.Println(res1) // >>> OK + + res2, err := rdb.Type(ctx, "thermometer:1").Result() + + if err != nil { + panic(err) + } + + fmt.Println(res2) // >>> TSDB-TYPE + + res3, err := rdb.TSInfo(ctx, "thermometer:1").Result() + + if err != nil { + panic(err) + } + + fmt.Println(res3["totalSamples"]) // >>> 0 + // STEP_END + + // STEP_START create_retention + res4, err := rdb.TSAddWithArgs( + ctx, + "thermometer:2", + 1, 10.8, + &redis.TSOptions{ + Retention: 100, + }, + ).Result() + + if err != nil { + panic(err) + } + + fmt.Println(res4) // >>> 1 + + res5, err := rdb.TSInfo(ctx, "thermometer:2").Result() + + if err != nil { + panic(err) + } + + fmt.Println(res5["retentionTime"]) // >>> 100 + // STEP_END + + // STEP_START create_labels + res6, err := rdb.TSAddWithArgs( + ctx, + "thermometer:3", + 1, 10.4, + &redis.TSOptions{ + Labels: map[string]string{"location": "UK", "type": "Mercury"}, + }, + ).Result() + + if err != nil { + panic(err) + } + + fmt.Println(res6) // >>> 1 + + res7, err := rdb.TSInfo(ctx, "thermometer:3").Result() + + if err != nil { + panic(err) + } + + fmt.Println(res7["labels"]) + // >>> map[location:UK type:Mercury] + // STEP_END + + // Output: + // OK + // TSDB-TYPE + // 0 + // 1 + // 100 + // 1 + // map[location:UK type:Mercury] +} + +func ExampleClient_timeseries_add() { + ctx := context.Background() + + rdb := redis.NewClient(&redis.Options{ + Addr: "localhost:6379", + Password: "", // no password set + DB: 0, // use default DB + }) + + // REMOVE_START + // make sure we are working with fresh database + rdb.FlushDB(ctx) + rdb.Del(ctx, "thermometer:1", "thermometer:2") + rdb.TSCreate(ctx, "thermometer:1") + rdb.TSCreate(ctx, "thermometer:2") + // REMOVE_END + + // STEP_START madd + res1, err := rdb.TSMAdd(ctx, [][]interface{}{ + {"thermometer:1", 1, 9.2}, + {"thermometer:1", 2, 9.9}, + {"thermometer:2", 2, 10.3}, + }).Result() + + if err != nil { + panic(err) + } + + fmt.Println(res1) // >>> [1 2 2] + // STEP_END + + // STEP_START get + // The last recorded temperature for thermometer:2 + // was 10.3 at time 2. + res2, err := rdb.TSGet(ctx, "thermometer:2").Result() + + if err != nil { + panic(err) + } + + fmt.Println(res2) + // >>> {2 10.3} + // STEP_END + + // Output: + // [1 2 2] + // {2 10.3} +} + +func ExampleClient_timeseries_range() { + ctx := context.Background() + + rdb := redis.NewClient(&redis.Options{ + Addr: "localhost:6379", + Password: "", // no password set + DB: 0, // use default DB + }) + + // REMOVE_START + // make sure we are working with fresh database + rdb.FlushDB(ctx) + rdb.Del(ctx, "rg:1") + // REMOVE_END + + // STEP_START range + // Add 5 data points to a time series named "rg:1". + res1, err := rdb.TSCreate(ctx, "rg:1").Result() + + if err != nil { + panic(err) + } + + fmt.Println(res1) // >>> OK + + res2, err := rdb.TSMAdd(ctx, [][]interface{}{ + {"rg:1", 0, 18}, + {"rg:1", 1, 14}, + {"rg:1", 2, 22}, + {"rg:1", 3, 18}, + {"rg:1", 4, 24}, + }).Result() + + if err != nil { + panic(err) + } + + fmt.Println(res2) // >>> [0 1 2 3 4] + + // Retrieve all the data points in ascending order. + // Note: use 0 and `math.MaxInt64` instead of - and + + // to denote the minimum and maximum possible timestamps. + res3, err := rdb.TSRange(ctx, "rg:1", + 0, math.MaxInt64, + ).Result() + + if err != nil { + panic(err) + } + + fmt.Println(res3) + // >>> [{0 18} {1 14} {2 22} {3 18} {4 24}] + + // Retrieve data points up to time 1 (inclusive). + res4, err := rdb.TSRange(ctx, "rg:1", 0, 1).Result() + + if err != nil { + panic(err) + } + + fmt.Println(res4) + // >>> [{0 18} {1 14}] + + // Retrieve data points from time 3 onwards. + res5, err := rdb.TSRange(ctx, "rg:1", 3, math.MaxInt64).Result() + + if err != nil { + panic(err) + } + + fmt.Println(res5) + // >>> [{3 18} {4 24}] + + // Retrieve all the data points in descending order. + res6, err := rdb.TSRevRange(ctx, "rg:1", 0, math.MaxInt64).Result() + + if err != nil { + panic(err) + } + + fmt.Println(res6) + // >>> [{4 24} {3 18} {2 22} {1 14} {0 18}] + + // Retrieve data points up to time 1 (inclusive), but return them + // in descending order. + res7, err := rdb.TSRevRange(ctx, "rg:1", 0, 1).Result() + + if err != nil { + panic(err) + } + + fmt.Println(res7) + // >>> [{1 14} {0 18}] + // STEP_END + + // STEP_START range_filter + res8, err := rdb.TSRangeWithArgs( + ctx, + "rg:1", + 0, math.MaxInt64, + &redis.TSRangeOptions{ + FilterByTS: []int{0, 2, 4}, + }, + ).Result() + + if err != nil { + panic(err) + } + + fmt.Println(res8) // >>> [{0 18} {2 22} {4 24}] + + res9, err := rdb.TSRevRangeWithArgs( + ctx, + "rg:1", + 0, math.MaxInt64, + &redis.TSRevRangeOptions{ + FilterByTS: []int{0, 2, 4}, + FilterByValue: []int{20, 25}, + }, + ).Result() + + if err != nil { + panic(err) + } + + fmt.Println(res9) // >>> [{4 24} {2 22}] + + res10, err := rdb.TSRevRangeWithArgs( + ctx, + "rg:1", + 0, math.MaxInt64, + &redis.TSRevRangeOptions{ + FilterByTS: []int{0, 2, 4}, + FilterByValue: []int{22, 22}, + }, + ).Result() + + if err != nil { + panic(err) + } + + fmt.Println(res10) // >>> [{2 22}] + // STEP_END + + // Output: + // OK + // [0 1 2 3 4] + // [{0 18} {1 14} {2 22} {3 18} {4 24}] + // [{0 18} {1 14}] + // [{3 18} {4 24}] + // [{4 24} {3 18} {2 22} {1 14} {0 18}] + // [{1 14} {0 18}] + // [{0 18} {2 22} {4 24}] + // [{4 24} {2 22}] + // [{2 22}] +} + +func ExampleClient_timeseries_query_multi() { + ctx := context.Background() + + rdb := redis.NewClient(&redis.Options{ + Addr: "localhost:6379", + Password: "", // no password set + DB: 0, // use default DB + }) + + // REMOVE_START + // make sure we are working with fresh database + rdb.FlushDB(ctx) + rdb.Del(ctx, "rg:2", "rg:3", "rg:4") + // REMOVE_END + + // STEP_START query_multi + // Create three new "rg:" time series (two in the US + // and one in the UK, with different units) and add some + // data points. + res20, err := rdb.TSCreateWithArgs(ctx, "rg:2", &redis.TSOptions{ + Labels: map[string]string{"location": "us", "unit": "cm"}, + }).Result() + + if err != nil { + panic(err) + } + + fmt.Println(res20) // >>> OK + + res21, err := rdb.TSCreateWithArgs(ctx, "rg:3", &redis.TSOptions{ + Labels: map[string]string{"location": "us", "unit": "in"}, + }).Result() + + if err != nil { + panic(err) + } + + fmt.Println(res21) // >>> OK + + res22, err := rdb.TSCreateWithArgs(ctx, "rg:4", &redis.TSOptions{ + Labels: map[string]string{"location": "uk", "unit": "mm"}, + }).Result() + + if err != nil { + panic(err) + } + + fmt.Println(res22) // >>> OK + + res23, err := rdb.TSMAdd(ctx, [][]interface{}{ + {"rg:2", 0, 1.8}, + {"rg:3", 0, 0.9}, + {"rg:4", 0, 25}, + }).Result() + + if err != nil { + panic(err) + } + + fmt.Println(res23) // >>> [0 0 0] + + res24, err := rdb.TSMAdd(ctx, [][]interface{}{ + {"rg:2", 1, 2.1}, + {"rg:3", 1, 0.77}, + {"rg:4", 1, 18}, + }).Result() + + if err != nil { + panic(err) + } + + fmt.Println(res24) // >>> [1 1 1] + + res25, err := rdb.TSMAdd(ctx, [][]interface{}{ + {"rg:2", 2, 2.3}, + {"rg:3", 2, 1.1}, + {"rg:4", 2, 21}, + }).Result() + + if err != nil { + panic(err) + } + + fmt.Println(res25) // >>> [2 2 2] + + res26, err := rdb.TSMAdd(ctx, [][]interface{}{ + {"rg:2", 3, 1.9}, + {"rg:3", 3, 0.81}, + {"rg:4", 3, 19}, + }).Result() + + if err != nil { + panic(err) + } + + fmt.Println(res26) // >>> [3 3 3] + + res27, err := rdb.TSMAdd(ctx, [][]interface{}{ + {"rg:2", 4, 1.78}, + {"rg:3", 4, 0.74}, + {"rg:4", 4, 23}, + }).Result() + + if err != nil { + panic(err) + } + + fmt.Println(res27) // >>> [4 4 4] + + // Retrieve the last data point from each US time series. + res28, err := rdb.TSMGet(ctx, []string{"location=us"}).Result() + + if err != nil { + panic(err) + } + + res28Keys := slices.Collect(maps.Keys(res28)) + sort.Strings(res28Keys) + + for _, k := range res28Keys { + labels := res28[k][0].(map[interface{}]interface{}) + + labelKeys := make([]string, 0, len(labels)) + + for lk := range labels { + labelKeys = append(labelKeys, lk.(string)) + } + + sort.Strings(labelKeys) + + fmt.Printf("%v:\n", k) + + for _, lk := range labelKeys { + fmt.Printf(" %v: %v\n", lk, labels[lk]) + } + + fmt.Printf(" %v\n", res28[k][1]) + } + // >>> rg:2: + // >>> {4 1.78} + // >>> rg:3: + // >>> {4 0.74} + + // Retrieve the same data points, but include the `unit` + // label in the results. + res29, err := rdb.TSMGetWithArgs(ctx, []string{"location=us"}, &redis.TSMGetOptions{ + SelectedLabels: []interface{}{"unit"}, + }).Result() + + if err != nil { + panic(err) + } + + res29Keys := slices.Collect(maps.Keys(res29)) + sort.Strings(res29Keys) + + for _, k := range res29Keys { + labels := res29[k][0].(map[interface{}]interface{}) + + labelKeys := make([]string, 0, len(labels)) + + for lk := range labels { + labelKeys = append(labelKeys, lk.(string)) + } + + sort.Strings(labelKeys) + + fmt.Printf("%v:\n", k) + + for _, lk := range labelKeys { + fmt.Printf(" %v: %v\n", lk, labels[lk]) + } + + fmt.Printf(" %v\n", res29[k][1]) + } + + // >>> rg:2: + // >>> unit: cm + // >>> [4 1.78] + // >>> rg:3: + // >>> unit: in + // >>> [4 0.74] + + // Retrieve data points up to time 2 (inclusive) from all + // time series that use millimeters as the unit. Include all + // labels in the results. + res30, err := rdb.TSMRangeWithArgs( + ctx, + 0, 2, + []string{"unit=mm"}, + &redis.TSMRangeOptions{ + WithLabels: true, + }, + ).Result() + + if err != nil { + panic(err) + } + + res30Keys := slices.Collect(maps.Keys(res30)) + sort.Strings(res30Keys) + + for _, k := range res30Keys { + labels := res30[k][0].(map[interface{}]interface{}) + labelKeys := make([]string, 0, len(labels)) + + for lk := range labels { + labelKeys = append(labelKeys, lk.(string)) + } + + sort.Strings(labelKeys) + + fmt.Printf("%v:\n", k) + + for _, lk := range labelKeys { + fmt.Printf(" %v: %v\n", lk, labels[lk]) + } + + fmt.Printf(" Aggregators: %v\n", res30[k][1]) + fmt.Printf(" %v\n", res30[k][2]) + } + // >>> rg:4: + // >>> location: uk + // >>> unit: mm + // >>> Aggregators: map[aggregators:[]] + // >>> Data points: [{0 25} {1 18} {2 21}] + + // Retrieve data points from time 1 to time 3 (inclusive) from + // all time series that use centimeters or millimeters as the unit, + // but only return the `location` label. Return the results + // in descending order of timestamp. + res31, err := rdb.TSMRevRangeWithArgs( + ctx, + 1, 3, + []string{"unit=(cm,mm)"}, + &redis.TSMRevRangeOptions{ + SelectedLabels: []interface{}{"location"}, + }, + ).Result() + + if err != nil { + panic(err) + } + res31Keys := slices.Collect(maps.Keys(res31)) + sort.Strings(res31Keys) + + for _, k := range res31Keys { + labels := res31[k][0].(map[interface{}]interface{}) + labelKeys := make([]string, 0, len(labels)) + + for lk := range labels { + labelKeys = append(labelKeys, lk.(string)) + } + + sort.Strings(labelKeys) + + fmt.Printf("%v:\n", k) + + for _, lk := range labelKeys { + fmt.Printf(" %v: %v\n", lk, labels[lk]) + } + + fmt.Printf(" Aggregators: %v\n", res31[k][1]) + fmt.Printf(" %v\n", res31[k][2]) + } + // STEP_END + + // Output: + // OK + // OK + // OK + // [0 0 0] + // [1 1 1] + // [2 2 2] + // [3 3 3] + // [4 4 4] + // rg:2: + // [4 1.78] + // rg:3: + // [4 0.74] + // rg:2: + // unit: cm + // [4 1.78] + // rg:3: + // unit: in + // [4 0.74] + // rg:4: + // location: uk + // unit: mm + // Aggregators: map[aggregators:[]] + // [[0 25] [1 18] [2 21]] + // rg:2: + // location: us + // Aggregators: map[aggregators:[]] + // [[3 1.9] [2 2.3] [1 2.1]] + // rg:4: + // location: uk + // Aggregators: map[aggregators:[]] + // [[3 19] [2 21] [1 18]] +} + +func ExampleClient_timeseries_aggregation() { + ctx := context.Background() + + rdb := redis.NewClient(&redis.Options{ + Addr: "localhost:6379", + Password: "", // no password set + DB: 0, // use default DB + }) + + // REMOVE_START + // make sure we are working with fresh database + rdb.FlushDB(ctx) + rdb.Del(ctx, "sensor3") + // REMOVE_END + + // STEP_START aggregation + res1, err := rdb.TSCreate(ctx, "sensor3").Result() + + if err != nil { + panic(err) + } + + fmt.Println(res1) // >>> OK + + for i := 1; i <= 10; i++ { + _, err := rdb.TSAdd(ctx, "sensor3", int64(i), float64(i*2)).Result() + + if err != nil { + panic(err) + } + } + + res2, err := rdb.TSRangeWithArgs( + ctx, + "sensor3", + 0, math.MaxInt64, + &redis.TSRangeOptions{ + Aggregator: redis.Avg, + BucketDuration: 5, + }, + ).Result() + + if err != nil { + panic(err) + } + + fmt.Println(res2) // >>> (0, 6.0) (5, 16.0) + + res3, err := rdb.TSRangeWithArgs( + ctx, + "sensor3", + 0, math.MaxInt64, + &redis.TSRangeOptions{ + Aggregator: redis.Min, + BucketDuration: 5, + }, + ).Result() + + if err != nil { + panic(err) + } + + fmt.Println(res3) // >>> (0, 2.0) (5, 12.0) + + res4, err := rdb.TSRangeWithArgs( + ctx, + "sensor3", + 0, math.MaxInt64, + &redis.TSRangeOptions{ + Aggregator: redis.Max, + BucketDuration: 5, + }, + ).Result() + + if err != nil { + panic(err) + } + + fmt.Println(res4) // >>> (0, 10.0) (5, 20.0) + // STEP_END + + // Output: + // OK + // [{0 5} {5 14} {10 20}] + // [{0 2} {5 10} {10 20}] + // [{0 8} {5 18} {10 20}] +} + +func ExampleClient_timeseries_downsampling() { + ctx := context.Background() + + rdb := redis.NewClient(&redis.Options{ + Addr: "localhost:6379", + Password: "", // no password set + DB: 0, // use default DB + }) + + // REMOVE_START + // make sure we are working with fresh database + rdb.FlushDB(ctx) + rdb.Del(ctx, "wind:1", "wind:2", "wind:3", "wind:4") + // REMOVE_END + + // STEP_START downsampling + res1, err := rdb.TSCreate(ctx, "wind:1").Result() + + if err != nil { + panic(err) + } + + fmt.Println(res1) // >>> OK + + res2, err := rdb.TSCreate(ctx, "wind:2").Result() + + if err != nil { + panic(err) + } + + fmt.Println(res2) // >>> OK + + res3, err := rdb.TSCreateRule(ctx, "wind:1", "wind:2", redis.Avg, 3600000).Result() + + if err != nil { + panic(err) + } + + fmt.Println(res3) // >>> OK + + res4, err := rdb.TSCreate(ctx, "wind:3").Result() + + if err != nil { + panic(err) + } + + fmt.Println(res4) // >>> OK + + res5, err := rdb.TSCreateRule(ctx, "wind:1", "wind:3", redis.Max, 3600000).Result() + + if err != nil { + panic(err) + } + + fmt.Println(res5) // >>> OK + + res6, err := rdb.TSCreate(ctx, "wind:4").Result() + + if err != nil { + panic(err) + } + + fmt.Println(res6) // >>> OK + + res7, err := rdb.TSCreateRule(ctx, "wind:1", "wind:4", redis.Min, 3600000).Result() + if err != nil { + panic(err) + } + fmt.Println(res7) // >>> OK + + samples := [][]interface{}{ + {"wind:1", 1000, 15}, + {"wind:1", 1500, 16}, + {"wind:1", 2000, 17}, + {"wind:1", 2500, 14}, + {"wind:1", 3000, 13}, + {"wind:1", 3600000 + 1000, 20}, + {"wind:1", 3600000 + 1500, 22}, + {"wind:1", 3600000 + 2000, 24}, + {"wind:1", 3600000 + 2500, 19}, + {"wind:1", 3600000 + 3000, 18}, + } + + _, err = rdb.TSMAdd(ctx, samples).Result() + + if err != nil { + panic(err) + } + + res8, err := rdb.TSRange(ctx, "wind:2", math.MinInt64, math.MaxInt64).Result() + + if err != nil { + panic(err) + } + + fmt.Print("Hourly average wind speed: ") + for _, dp := range res8 { + fmt.Printf("(%.0f, %.1f) ", float64(dp.Timestamp), dp.Value) + } + fmt.Println() // >>> Hourly average wind speed: (0, 15.0) (3600000, 20.6) + + res9, err := rdb.TSRange(ctx, "wind:3", math.MinInt64, math.MaxInt64).Result() + if err != nil { + panic(err) + } + fmt.Print("Hourly maximum wind speed: ") + for _, dp := range res9 { + fmt.Printf("(%.0f, %.1f) ", float64(dp.Timestamp), dp.Value) + } + fmt.Println() // >>> Hourly maximum wind speed: (0, 17.0) (3600000, 24.0) + + res10, err := rdb.TSRange(ctx, "wind:4", math.MinInt64, math.MaxInt64).Result() + if err != nil { + panic(err) + } + fmt.Print("Hourly minimum wind speed: ") + for _, dp := range res10 { + fmt.Printf("(%.0f, %.1f) ", float64(dp.Timestamp), dp.Value) + } + fmt.Println() // >>> Hourly minimum wind speed: (0, 13.0) (3600000, 18.0) + // STEP_END + + // Output: + // OK + // OK + // OK + // OK + // OK + // OK + // OK + // Hourly average wind speed: (0, 15.0) (3600000, 20.6) + // Hourly maximum wind speed: (0, 17.0) (3600000, 24.0) + // Hourly minimum wind speed: (0, 13.0) (3600000, 18.0) +} + +func ExampleClient_timeseries_compaction() { + ctx := context.Background() + + rdb := redis.NewClient(&redis.Options{ + Addr: "localhost:6379", + Password: "", // no password set + DB: 0, // use default DB + }) + + // REMOVE_START + // make sure we are working with fresh database + rdb.FlushDB(ctx) + rdb.Del(ctx, "hyg:1", "hyg:compacted") + // REMOVE_END + + // STEP_START compaction + res1, err := rdb.TSCreate(ctx, "hyg:1").Result() + if err != nil { + panic(err) + } + fmt.Println(res1) // >>> OK + + res2, err := rdb.TSCreate(ctx, "hyg:compacted").Result() + if err != nil { + panic(err) + } + fmt.Println(res2) // >>> OK + + res3, err := rdb.TSCreateRuleWithArgs(ctx, "hyg:1", "hyg:compacted", redis.Twa, 60000, &redis.TSCreateRuleOptions{}).Result() + if err != nil { + panic(err) + } + fmt.Println(res3) // >>> OK + + samples := [][]interface{}{ + {"hyg:1", 1000, 70}, + {"hyg:1", 15000, 72}, + {"hyg:1", 29000, 75}, + {"hyg:1", 40000, 68}, + {"hyg:1", 55000, 65}, + {"hyg:1", 60000 + 1000, 63}, + {"hyg:1", 60000 + 15000, 60}, + {"hyg:1", 60000 + 29000, 58}, + {"hyg:1", 60000 + 40000, 62}, + {"hyg:1", 60000 + 55000, 65}, + } + + _, err = rdb.TSMAdd(ctx, samples).Result() + if err != nil { + panic(err) + } + + res4, err := rdb.TSRange(ctx, "hyg:compacted", math.MinInt64, math.MaxInt64).Result() + if err != nil { + panic(err) + } + fmt.Print("Compacted humidity data (time-weighted average): ") + for _, dp := range res4 { + fmt.Printf("(%.0f, %.1f) ", float64(dp.Timestamp), dp.Value) + } + fmt.Println() // >>> Compacted humidity data (time-weighted average): (0, 70.5) (60000, 61.5) + // STEP_END + + // Output: + // OK + // OK + // OK + // Compacted humidity data (time-weighted average): (0, 70.5) (60000, 61.5) +} From ff626035e5b3ee5b297a896172647ebead9866e5 Mon Sep 17 00:00:00 2001 From: Andy Stark Date: Tue, 22 Jul 2025 15:13:48 +0100 Subject: [PATCH 2/5] DOC-5472 added agg bucket examples --- doctests/timeseries_tut_test.go | 122 ++++++++++++++++++++++++-------- 1 file changed, 94 insertions(+), 28 deletions(-) diff --git a/doctests/timeseries_tut_test.go b/doctests/timeseries_tut_test.go index 45bf9448e..708c53f4e 100644 --- a/doctests/timeseries_tut_test.go +++ b/doctests/timeseries_tut_test.go @@ -468,9 +468,13 @@ func ExampleClient_timeseries_query_multi() { // Retrieve the same data points, but include the `unit` // label in the results. - res29, err := rdb.TSMGetWithArgs(ctx, []string{"location=us"}, &redis.TSMGetOptions{ - SelectedLabels: []interface{}{"unit"}, - }).Result() + res29, err := rdb.TSMGetWithArgs( + ctx, + []string{"location=us"}, + &redis.TSMGetOptions{ + SelectedLabels: []interface{}{"unit"}, + }, + ).Result() if err != nil { panic(err) @@ -509,6 +513,8 @@ func ExampleClient_timeseries_query_multi() { // Retrieve data points up to time 2 (inclusive) from all // time series that use millimeters as the unit. Include all // labels in the results. + // Note that the `aggregators` field is empty if no + // aggregators are specified. res30, err := rdb.TSMRangeWithArgs( ctx, 0, 2, @@ -548,7 +554,7 @@ func ExampleClient_timeseries_query_multi() { // >>> location: uk // >>> unit: mm // >>> Aggregators: map[aggregators:[]] - // >>> Data points: [{0 25} {1 18} {2 21}] + // >>> [{0 25} {1 18} {2 21}] // Retrieve data points from time 1 to time 3 (inclusive) from // all time series that use centimeters or millimeters as the unit, @@ -566,6 +572,7 @@ func ExampleClient_timeseries_query_multi() { if err != nil { panic(err) } + res31Keys := slices.Collect(maps.Keys(res31)) sort.Strings(res31Keys) @@ -588,6 +595,14 @@ func ExampleClient_timeseries_query_multi() { fmt.Printf(" Aggregators: %v\n", res31[k][1]) fmt.Printf(" %v\n", res31[k][2]) } + // >>> rg:2: + // >>> location: us + // >>> Aggregators: map[aggregators:[]] + // >>> [{3 1.9} {2 2.3} {1 2.1}] + // >>> rg:4: + // >>> location: uk + // >>> Aggregators: map[aggregators:[]] + // >>> [{3 19} {2 21} {1 18}] // STEP_END // Output: @@ -636,33 +651,38 @@ func ExampleClient_timeseries_aggregation() { // REMOVE_START // make sure we are working with fresh database rdb.FlushDB(ctx) - rdb.Del(ctx, "sensor3") + rdb.Del(ctx, "rg:2") // REMOVE_END - // STEP_START aggregation - res1, err := rdb.TSCreate(ctx, "sensor3").Result() + // Setup data for aggregation example + _, err := rdb.TSCreateWithArgs(ctx, "rg:2", &redis.TSOptions{ + Labels: map[string]string{"location": "us", "unit": "cm"}, + }).Result() if err != nil { panic(err) } - fmt.Println(res1) // >>> OK - - for i := 1; i <= 10; i++ { - _, err := rdb.TSAdd(ctx, "sensor3", int64(i), float64(i*2)).Result() + _, err = rdb.TSMAdd(ctx, [][]interface{}{ + {"rg:2", 0, 1.8}, + {"rg:2", 1, 2.1}, + {"rg:2", 2, 2.3}, + {"rg:2", 3, 1.9}, + {"rg:2", 4, 1.78}, + }).Result() - if err != nil { - panic(err) - } + if err != nil { + panic(err) } - res2, err := rdb.TSRangeWithArgs( + // STEP_START agg + res32, err := rdb.TSRangeWithArgs( ctx, - "sensor3", + "rg:2", 0, math.MaxInt64, &redis.TSRangeOptions{ Aggregator: redis.Avg, - BucketDuration: 5, + BucketDuration: 2, }, ).Result() @@ -670,15 +690,60 @@ func ExampleClient_timeseries_aggregation() { panic(err) } - fmt.Println(res2) // >>> (0, 6.0) (5, 16.0) + fmt.Println(res32) + // >>> [{0 1.9500000000000002} {2 2.0999999999999996} {4 1.78}] + // STEP_END + + // Output: + // [{0 1.9500000000000002} {2 2.0999999999999996} {4 1.78}] +} +func ExampleClient_timeseries_agg_bucket() { + ctx := context.Background() + + rdb := redis.NewClient(&redis.Options{ + Addr: "localhost:6379", + Password: "", // no password set + DB: 0, // use default DB + }) + + // REMOVE_START + // make sure we are working with fresh database + rdb.FlushDB(ctx) + rdb.Del(ctx, "sensor3") + // REMOVE_END + + // STEP_START agg_bucket + res1, err := rdb.TSCreate(ctx, "sensor3").Result() + + if err != nil { + panic(err) + } + + fmt.Println(res1) // >>> OK + + res2, err := rdb.TSMAdd(ctx, [][]interface{}{ + {"sensor3", 10, 1000}, + {"sensor3", 20, 2000}, + {"sensor3", 30, 3000}, + {"sensor3", 40, 4000}, + {"sensor3", 50, 5000}, + {"sensor3", 60, 6000}, + {"sensor3", 70, 7000}, + }).Result() + + if err != nil { + panic(err) + } + + fmt.Println(res2) // >>> [10 20 30 40 50 60 70] res3, err := rdb.TSRangeWithArgs( ctx, "sensor3", - 0, math.MaxInt64, + 10, 70, &redis.TSRangeOptions{ Aggregator: redis.Min, - BucketDuration: 5, + BucketDuration: 25, }, ).Result() @@ -686,15 +751,16 @@ func ExampleClient_timeseries_aggregation() { panic(err) } - fmt.Println(res3) // >>> (0, 2.0) (5, 12.0) + fmt.Println(res3) // >>> [{0 1000} {25 3000} {50 5000}] res4, err := rdb.TSRangeWithArgs( ctx, "sensor3", - 0, math.MaxInt64, + 10, 70, &redis.TSRangeOptions{ - Aggregator: redis.Max, - BucketDuration: 5, + Aggregator: redis.Min, + BucketDuration: 25, + Align: "START", }, ).Result() @@ -702,14 +768,14 @@ func ExampleClient_timeseries_aggregation() { panic(err) } - fmt.Println(res4) // >>> (0, 10.0) (5, 20.0) + fmt.Println(res4) // >>> [{10 1000} {35 4000} {60 6000}] // STEP_END // Output: // OK - // [{0 5} {5 14} {10 20}] - // [{0 2} {5 10} {10 20}] - // [{0 8} {5 18} {10 20}] + // [10 20 30 40 50 60 70] + // [{0 1000} {25 3000} {50 5000}] + // [{10 1000} {35 4000} {60 6000}] } func ExampleClient_timeseries_downsampling() { From f55fb2a076de0a191104516eff97281359416b86 Mon Sep 17 00:00:00 2001 From: Andy Stark Date: Wed, 23 Jul 2025 10:41:02 +0100 Subject: [PATCH 3/5] DOC-5472 time series doc examples --- doctests/timeseries_tut_test.go | 398 +++++++++++++++++++++++++------- 1 file changed, 315 insertions(+), 83 deletions(-) diff --git a/doctests/timeseries_tut_test.go b/doctests/timeseries_tut_test.go index 708c53f4e..f4a0b78ae 100644 --- a/doctests/timeseries_tut_test.go +++ b/doctests/timeseries_tut_test.go @@ -87,7 +87,10 @@ func ExampleClient_timeseries_create() { "thermometer:3", 1, 10.4, &redis.TSOptions{ - Labels: map[string]string{"location": "UK", "type": "Mercury"}, + Labels: map[string]string{ + "location": "UK", + "type": "Mercury", + }, }, ).Result() @@ -513,8 +516,8 @@ func ExampleClient_timeseries_query_multi() { // Retrieve data points up to time 2 (inclusive) from all // time series that use millimeters as the unit. Include all // labels in the results. - // Note that the `aggregators` field is empty if no - // aggregators are specified. + // Note that the `aggregators` field is empty if you don't + // specify any aggregators. res30, err := rdb.TSMRangeWithArgs( ctx, 0, 2, @@ -752,7 +755,9 @@ func ExampleClient_timeseries_agg_bucket() { } fmt.Println(res3) // >>> [{0 1000} {25 3000} {50 5000}] + // STEP_END + // STEP_START agg_align res4, err := rdb.TSRangeWithArgs( ctx, "sensor3", @@ -778,7 +783,7 @@ func ExampleClient_timeseries_agg_bucket() { // [{10 1000} {35 4000} {60 6000}] } -func ExampleClient_timeseries_downsampling() { +func ExampleClient_timeseries_aggmulti() { ctx := context.Background() rdb := redis.NewClient(&redis.Options{ @@ -793,127 +798,323 @@ func ExampleClient_timeseries_downsampling() { rdb.Del(ctx, "wind:1", "wind:2", "wind:3", "wind:4") // REMOVE_END - // STEP_START downsampling - res1, err := rdb.TSCreate(ctx, "wind:1").Result() + // STEP_START agg_multi + res37, err := rdb.TSCreateWithArgs(ctx, "wind:1", &redis.TSOptions{ + Labels: map[string]string{"country": "uk"}, + }).Result() if err != nil { panic(err) } - fmt.Println(res1) // >>> OK + fmt.Println(res37) // >>> OK + + res38, err := rdb.TSCreateWithArgs(ctx, "wind:2", &redis.TSOptions{ + Labels: map[string]string{"country": "uk"}, + }).Result() + + if err != nil { + panic(err) + } + + fmt.Println(res38) // >>> OK - res2, err := rdb.TSCreate(ctx, "wind:2").Result() + res39, err := rdb.TSCreateWithArgs(ctx, "wind:3", &redis.TSOptions{ + Labels: map[string]string{"country": "us"}, + }).Result() + + if err != nil { + panic(err) + } + + fmt.Println(res39) // >>> OK + + res40, err := rdb.TSCreateWithArgs(ctx, "wind:4", &redis.TSOptions{ + Labels: map[string]string{"country": "us"}, + }).Result() if err != nil { panic(err) } - fmt.Println(res2) // >>> OK + fmt.Println(res40) // >>> OK - res3, err := rdb.TSCreateRule(ctx, "wind:1", "wind:2", redis.Avg, 3600000).Result() + res41, err := rdb.TSMAdd(ctx, [][]interface{}{ + {"wind:1", 1, 12}, + {"wind:2", 1, 18}, + {"wind:3", 1, 5}, + {"wind:4", 1, 20}, + }).Result() if err != nil { panic(err) } - fmt.Println(res3) // >>> OK + fmt.Println(res41) // >>> [1 1 1 1] - res4, err := rdb.TSCreate(ctx, "wind:3").Result() + res42, err := rdb.TSMAdd(ctx, [][]interface{}{ + {"wind:1", 2, 14}, + {"wind:2", 2, 21}, + {"wind:3", 2, 4}, + {"wind:4", 2, 25}, + }).Result() if err != nil { panic(err) } - fmt.Println(res4) // >>> OK + fmt.Println(res42) // >>> [2 2 2 2] - res5, err := rdb.TSCreateRule(ctx, "wind:1", "wind:3", redis.Max, 3600000).Result() + res43, err := rdb.TSMAdd(ctx, [][]interface{}{ + {"wind:1", 3, 10}, + {"wind:2", 3, 24}, + {"wind:3", 3, 8}, + {"wind:4", 3, 18}, + }).Result() if err != nil { panic(err) } - fmt.Println(res5) // >>> OK + fmt.Println(res43) // >>> [3 3 3 3] - res6, err := rdb.TSCreate(ctx, "wind:4").Result() + // The result pairs contain the timestamp and the maximum sample value + // for the country at that timestamp. + res44, err := rdb.TSMRangeWithArgs( + ctx, + 0, math.MaxInt64, + []string{"country=(us,uk)"}, + &redis.TSMRangeOptions{ + GroupByLabel: "country", + Reducer: "max", + }, + ).Result() if err != nil { panic(err) } - fmt.Println(res6) // >>> OK + res44Keys := slices.Collect(maps.Keys(res44)) + sort.Strings(res44Keys) + + for _, k := range res44Keys { + labels := res44[k][0].(map[interface{}]interface{}) + labelKeys := make([]string, 0, len(labels)) + + for lk := range labels { + labelKeys = append(labelKeys, lk.(string)) + } + + sort.Strings(labelKeys) + + fmt.Printf("%v:\n", k) + + for _, lk := range labelKeys { + fmt.Printf(" %v: %v\n", lk, labels[lk]) + } + + fmt.Printf(" %v\n", res44[k][1]) + fmt.Printf(" %v\n", res44[k][2]) + fmt.Printf(" %v\n", res44[k][3]) + } + // >>> country=uk: + // >>> map[reducers:[max]] + // >>> map[sources:[wind:1 wind:2]] + // >>> [[1 18] [2 21] [3 24]] + // >>> country=us: + // >>> map[reducers:[max]] + // >>> map[sources:[wind:3 wind:4]] + // >>> [[1 20] [2 25] [3 18]] + + // The result pairs contain the timestamp and the average sample value + // for the country at that timestamp. + res45, err := rdb.TSMRangeWithArgs( + ctx, + 0, math.MaxInt64, + []string{"country=(us,uk)"}, + &redis.TSMRangeOptions{ + GroupByLabel: "country", + Reducer: "avg", + }, + ).Result() + + if err != nil { + panic(err) + } + + res45Keys := slices.Collect(maps.Keys(res45)) + sort.Strings(res45Keys) + + for _, k := range res45Keys { + labels := res45[k][0].(map[interface{}]interface{}) + labelKeys := make([]string, 0, len(labels)) + + for lk := range labels { + labelKeys = append(labelKeys, lk.(string)) + } + + sort.Strings(labelKeys) + + fmt.Printf("%v:\n", k) + + for _, lk := range labelKeys { + fmt.Printf(" %v: %v\n", lk, labels[lk]) + } + + fmt.Printf(" %v\n", res45[k][1]) + fmt.Printf(" %v\n", res45[k][2]) + fmt.Printf(" %v\n", res45[k][3]) + } + // >>> country=uk: + // >>> map[reducers:[avg]] + // >>> map[sources:[wind:1 wind:2]] + // >>> [[1 15] [2 17.5] [3 17]] + // >>> country=us: + // >>> map[reducers:[avg]] + // >>> map[sources:[wind:3 wind:4]] + // >>> [[1 12.5] [2 14.5] [3 13]] + // STEP_END + + // Output: + // OK + // OK + // OK + // OK + // [1 1 1 1] + // [2 2 2 2] + // [3 3 3 3] + // country=uk: + // map[reducers:[max]] + // map[sources:[wind:1 wind:2]] + // [[1 18] [2 21] [3 24]] + // country=us: + // map[reducers:[max]] + // map[sources:[wind:3 wind:4]] + // [[1 20] [2 25] [3 18]] + // country=uk: + // map[reducers:[avg]] + // map[sources:[wind:1 wind:2]] + // [[1 15] [2 17.5] [3 17]] + // country=us: + // map[reducers:[avg]] + // map[sources:[wind:3 wind:4]] + // [[1 12.5] [2 14.5] [3 13]] +} + +func ExampleClient_timeseries_compaction() { + ctx := context.Background() + + rdb := redis.NewClient(&redis.Options{ + Addr: "localhost:6379", + Password: "", // no password set + DB: 0, // use default DB + }) + + // REMOVE_START + // make sure we are working with fresh database + rdb.FlushDB(ctx) + rdb.Del(ctx, "hyg:1", "hyg:compacted") + // REMOVE_END + + // STEP_START create_compaction + res45, err := rdb.TSCreate(ctx, "hyg:1").Result() - res7, err := rdb.TSCreateRule(ctx, "wind:1", "wind:4", redis.Min, 3600000).Result() if err != nil { panic(err) } - fmt.Println(res7) // >>> OK - samples := [][]interface{}{ - {"wind:1", 1000, 15}, - {"wind:1", 1500, 16}, - {"wind:1", 2000, 17}, - {"wind:1", 2500, 14}, - {"wind:1", 3000, 13}, - {"wind:1", 3600000 + 1000, 20}, - {"wind:1", 3600000 + 1500, 22}, - {"wind:1", 3600000 + 2000, 24}, - {"wind:1", 3600000 + 2500, 19}, - {"wind:1", 3600000 + 3000, 18}, + fmt.Println(res45) // >>> OK + + res46, err := rdb.TSCreate(ctx, "hyg:compacted").Result() + + if err != nil { + panic(err) } - _, err = rdb.TSMAdd(ctx, samples).Result() + fmt.Println(res46) // >>> OK + + res47, err := rdb.TSCreateRule( + ctx, "hyg:1", "hyg:compacted", redis.Min, 3, + ).Result() if err != nil { panic(err) } - res8, err := rdb.TSRange(ctx, "wind:2", math.MinInt64, math.MaxInt64).Result() + fmt.Println(res47) // >>> OK + + res48, err := rdb.TSInfo(ctx, "hyg:1").Result() if err != nil { panic(err) } - fmt.Print("Hourly average wind speed: ") - for _, dp := range res8 { - fmt.Printf("(%.0f, %.1f) ", float64(dp.Timestamp), dp.Value) + fmt.Println(res48["rules"]) // >>> [[hyg:compacted 3 MIN 0]] + + res49, err := rdb.TSInfo(ctx, "hyg:compacted").Result() + + if err != nil { + panic(err) } - fmt.Println() // >>> Hourly average wind speed: (0, 15.0) (3600000, 20.6) - res9, err := rdb.TSRange(ctx, "wind:3", math.MinInt64, math.MaxInt64).Result() + fmt.Println(res49["sourceKey"]) // >>> hyg:1 + // STEP_END + + // STEP_START comp_add + res50, err := rdb.TSMAdd(ctx, [][]interface{}{ + {"hyg:1", 0, 75}, + {"hyg:1", 1, 77}, + {"hyg:1", 2, 78}, + }).Result() + if err != nil { panic(err) } - fmt.Print("Hourly maximum wind speed: ") - for _, dp := range res9 { - fmt.Printf("(%.0f, %.1f) ", float64(dp.Timestamp), dp.Value) + + fmt.Println(res50) // >>> [0 1 2] + + res51, err := rdb.TSRange( + ctx, "hyg:compacted", 0, math.MaxInt64, + ).Result() + + if err != nil { + panic(err) } - fmt.Println() // >>> Hourly maximum wind speed: (0, 17.0) (3600000, 24.0) - res10, err := rdb.TSRange(ctx, "wind:4", math.MinInt64, math.MaxInt64).Result() + fmt.Println(res51) // >>> [] + + res52, err := rdb.TSAdd(ctx, "hyg:1", 3, 79).Result() + if err != nil { panic(err) } - fmt.Print("Hourly minimum wind speed: ") - for _, dp := range res10 { - fmt.Printf("(%.0f, %.1f) ", float64(dp.Timestamp), dp.Value) + + fmt.Println(res52) // >>> 3 + + res53, err := rdb.TSRange( + ctx, "hyg:compacted", 0, math.MaxInt64, + ).Result() + + if err != nil { + panic(err) } - fmt.Println() // >>> Hourly minimum wind speed: (0, 13.0) (3600000, 18.0) + + fmt.Println(res53) // >>> [{0 75}] // STEP_END // Output: // OK // OK // OK - // OK - // OK - // OK - // OK - // Hourly average wind speed: (0, 15.0) (3600000, 20.6) - // Hourly maximum wind speed: (0, 17.0) (3600000, 24.0) - // Hourly minimum wind speed: (0, 13.0) (3600000, 18.0) + // map[hyg:compacted:[3 MIN 0]] + // hyg:1 + // [0 1 2] + // [] + // 3 + // [{0 75}] } -func ExampleClient_timeseries_compaction() { +func ExampleClient_timeseries_delete() { ctx := context.Background() rdb := redis.NewClient(&redis.Options{ @@ -925,60 +1126,91 @@ func ExampleClient_timeseries_compaction() { // REMOVE_START // make sure we are working with fresh database rdb.FlushDB(ctx) - rdb.Del(ctx, "hyg:1", "hyg:compacted") + rdb.Del(ctx, "thermometer:1") + // Setup initial data + rdb.TSCreate(ctx, "thermometer:1") + rdb.TSMAdd(ctx, [][]interface{}{ + {"thermometer:1", 1, 9.2}, + {"thermometer:1", 2, 9.9}, + }) // REMOVE_END - // STEP_START compaction - res1, err := rdb.TSCreate(ctx, "hyg:1").Result() + // STEP_START del + res54, err := rdb.TSInfo(ctx, "thermometer:1").Result() + if err != nil { panic(err) } - fmt.Println(res1) // >>> OK - res2, err := rdb.TSCreate(ctx, "hyg:compacted").Result() + fmt.Println(res54["totalSamples"]) // >>> 2 + fmt.Println(res54["firstTimestamp"]) // >>> 1 + fmt.Println(res54["lastTimestamp"]) // >>> 2 + + res55, err := rdb.TSAdd(ctx, "thermometer:1", 3, 9.7).Result() + if err != nil { panic(err) } - fmt.Println(res2) // >>> OK - res3, err := rdb.TSCreateRuleWithArgs(ctx, "hyg:1", "hyg:compacted", redis.Twa, 60000, &redis.TSCreateRuleOptions{}).Result() + fmt.Println(res55) // >>> 3 + + res56, err := rdb.TSInfo(ctx, "thermometer:1").Result() + if err != nil { panic(err) } - fmt.Println(res3) // >>> OK - samples := [][]interface{}{ - {"hyg:1", 1000, 70}, - {"hyg:1", 15000, 72}, - {"hyg:1", 29000, 75}, - {"hyg:1", 40000, 68}, - {"hyg:1", 55000, 65}, - {"hyg:1", 60000 + 1000, 63}, - {"hyg:1", 60000 + 15000, 60}, - {"hyg:1", 60000 + 29000, 58}, - {"hyg:1", 60000 + 40000, 62}, - {"hyg:1", 60000 + 55000, 65}, + fmt.Println(res56["totalSamples"]) // >>> 3 + fmt.Println(res56["firstTimestamp"]) // >>> 1 + fmt.Println(res56["lastTimestamp"]) // >>> 3 + + res57, err := rdb.TSDel(ctx, "thermometer:1", 1, 2).Result() + + if err != nil { + panic(err) } - _, err = rdb.TSMAdd(ctx, samples).Result() + fmt.Println(res57) // >>> 2 + + res58, err := rdb.TSInfo(ctx, "thermometer:1").Result() + if err != nil { panic(err) } - res4, err := rdb.TSRange(ctx, "hyg:compacted", math.MinInt64, math.MaxInt64).Result() + fmt.Println(res58["totalSamples"]) // >>> 1 + fmt.Println(res58["firstTimestamp"]) // >>> 3 + fmt.Println(res58["lastTimestamp"]) // >>> 3 + + res59, err := rdb.TSDel(ctx, "thermometer:1", 3, 3).Result() + if err != nil { panic(err) } - fmt.Print("Compacted humidity data (time-weighted average): ") - for _, dp := range res4 { - fmt.Printf("(%.0f, %.1f) ", float64(dp.Timestamp), dp.Value) + + fmt.Println(res59) // >>> 1 + + res60, err := rdb.TSInfo(ctx, "thermometer:1").Result() + + if err != nil { + panic(err) } - fmt.Println() // >>> Compacted humidity data (time-weighted average): (0, 70.5) (60000, 61.5) + + fmt.Println(res60["totalSamples"]) // >>> 0 // STEP_END // Output: - // OK - // OK - // OK - // Compacted humidity data (time-weighted average): (0, 70.5) (60000, 61.5) + // 2 + // 1 + // 2 + // 3 + // 3 + // 1 + // 3 + // 2 + // 1 + // 3 + // 3 + // 1 + // 0 } From f138803b9deda3c0edd331b293cc8417710c524a Mon Sep 17 00:00:00 2001 From: Andy Stark Date: Wed, 30 Jul 2025 14:28:45 +0100 Subject: [PATCH 4/5] DOC-5472 removed black lines above error checks, following feedback --- doctests/timeseries_tut_test.go | 63 --------------------------------- 1 file changed, 63 deletions(-) diff --git a/doctests/timeseries_tut_test.go b/doctests/timeseries_tut_test.go index f4a0b78ae..d779f6827 100644 --- a/doctests/timeseries_tut_test.go +++ b/doctests/timeseries_tut_test.go @@ -32,7 +32,6 @@ func ExampleClient_timeseries_create() { // STEP_START create res1, err := rdb.TSCreate(ctx, "thermometer:1").Result() - if err != nil { panic(err) } @@ -40,7 +39,6 @@ func ExampleClient_timeseries_create() { fmt.Println(res1) // >>> OK res2, err := rdb.Type(ctx, "thermometer:1").Result() - if err != nil { panic(err) } @@ -48,7 +46,6 @@ func ExampleClient_timeseries_create() { fmt.Println(res2) // >>> TSDB-TYPE res3, err := rdb.TSInfo(ctx, "thermometer:1").Result() - if err != nil { panic(err) } @@ -65,7 +62,6 @@ func ExampleClient_timeseries_create() { Retention: 100, }, ).Result() - if err != nil { panic(err) } @@ -73,7 +69,6 @@ func ExampleClient_timeseries_create() { fmt.Println(res4) // >>> 1 res5, err := rdb.TSInfo(ctx, "thermometer:2").Result() - if err != nil { panic(err) } @@ -93,7 +88,6 @@ func ExampleClient_timeseries_create() { }, }, ).Result() - if err != nil { panic(err) } @@ -101,7 +95,6 @@ func ExampleClient_timeseries_create() { fmt.Println(res6) // >>> 1 res7, err := rdb.TSInfo(ctx, "thermometer:3").Result() - if err != nil { panic(err) } @@ -143,7 +136,6 @@ func ExampleClient_timeseries_add() { {"thermometer:1", 2, 9.9}, {"thermometer:2", 2, 10.3}, }).Result() - if err != nil { panic(err) } @@ -155,7 +147,6 @@ func ExampleClient_timeseries_add() { // The last recorded temperature for thermometer:2 // was 10.3 at time 2. res2, err := rdb.TSGet(ctx, "thermometer:2").Result() - if err != nil { panic(err) } @@ -187,7 +178,6 @@ func ExampleClient_timeseries_range() { // STEP_START range // Add 5 data points to a time series named "rg:1". res1, err := rdb.TSCreate(ctx, "rg:1").Result() - if err != nil { panic(err) } @@ -201,7 +191,6 @@ func ExampleClient_timeseries_range() { {"rg:1", 3, 18}, {"rg:1", 4, 24}, }).Result() - if err != nil { panic(err) } @@ -214,7 +203,6 @@ func ExampleClient_timeseries_range() { res3, err := rdb.TSRange(ctx, "rg:1", 0, math.MaxInt64, ).Result() - if err != nil { panic(err) } @@ -224,7 +212,6 @@ func ExampleClient_timeseries_range() { // Retrieve data points up to time 1 (inclusive). res4, err := rdb.TSRange(ctx, "rg:1", 0, 1).Result() - if err != nil { panic(err) } @@ -234,7 +221,6 @@ func ExampleClient_timeseries_range() { // Retrieve data points from time 3 onwards. res5, err := rdb.TSRange(ctx, "rg:1", 3, math.MaxInt64).Result() - if err != nil { panic(err) } @@ -244,7 +230,6 @@ func ExampleClient_timeseries_range() { // Retrieve all the data points in descending order. res6, err := rdb.TSRevRange(ctx, "rg:1", 0, math.MaxInt64).Result() - if err != nil { panic(err) } @@ -255,7 +240,6 @@ func ExampleClient_timeseries_range() { // Retrieve data points up to time 1 (inclusive), but return them // in descending order. res7, err := rdb.TSRevRange(ctx, "rg:1", 0, 1).Result() - if err != nil { panic(err) } @@ -273,7 +257,6 @@ func ExampleClient_timeseries_range() { FilterByTS: []int{0, 2, 4}, }, ).Result() - if err != nil { panic(err) } @@ -289,7 +272,6 @@ func ExampleClient_timeseries_range() { FilterByValue: []int{20, 25}, }, ).Result() - if err != nil { panic(err) } @@ -305,7 +287,6 @@ func ExampleClient_timeseries_range() { FilterByValue: []int{22, 22}, }, ).Result() - if err != nil { panic(err) } @@ -348,7 +329,6 @@ func ExampleClient_timeseries_query_multi() { res20, err := rdb.TSCreateWithArgs(ctx, "rg:2", &redis.TSOptions{ Labels: map[string]string{"location": "us", "unit": "cm"}, }).Result() - if err != nil { panic(err) } @@ -358,7 +338,6 @@ func ExampleClient_timeseries_query_multi() { res21, err := rdb.TSCreateWithArgs(ctx, "rg:3", &redis.TSOptions{ Labels: map[string]string{"location": "us", "unit": "in"}, }).Result() - if err != nil { panic(err) } @@ -368,7 +347,6 @@ func ExampleClient_timeseries_query_multi() { res22, err := rdb.TSCreateWithArgs(ctx, "rg:4", &redis.TSOptions{ Labels: map[string]string{"location": "uk", "unit": "mm"}, }).Result() - if err != nil { panic(err) } @@ -380,7 +358,6 @@ func ExampleClient_timeseries_query_multi() { {"rg:3", 0, 0.9}, {"rg:4", 0, 25}, }).Result() - if err != nil { panic(err) } @@ -392,7 +369,6 @@ func ExampleClient_timeseries_query_multi() { {"rg:3", 1, 0.77}, {"rg:4", 1, 18}, }).Result() - if err != nil { panic(err) } @@ -404,7 +380,6 @@ func ExampleClient_timeseries_query_multi() { {"rg:3", 2, 1.1}, {"rg:4", 2, 21}, }).Result() - if err != nil { panic(err) } @@ -416,7 +391,6 @@ func ExampleClient_timeseries_query_multi() { {"rg:3", 3, 0.81}, {"rg:4", 3, 19}, }).Result() - if err != nil { panic(err) } @@ -428,7 +402,6 @@ func ExampleClient_timeseries_query_multi() { {"rg:3", 4, 0.74}, {"rg:4", 4, 23}, }).Result() - if err != nil { panic(err) } @@ -437,7 +410,6 @@ func ExampleClient_timeseries_query_multi() { // Retrieve the last data point from each US time series. res28, err := rdb.TSMGet(ctx, []string{"location=us"}).Result() - if err != nil { panic(err) } @@ -478,7 +450,6 @@ func ExampleClient_timeseries_query_multi() { SelectedLabels: []interface{}{"unit"}, }, ).Result() - if err != nil { panic(err) } @@ -526,7 +497,6 @@ func ExampleClient_timeseries_query_multi() { WithLabels: true, }, ).Result() - if err != nil { panic(err) } @@ -571,7 +541,6 @@ func ExampleClient_timeseries_query_multi() { SelectedLabels: []interface{}{"location"}, }, ).Result() - if err != nil { panic(err) } @@ -661,7 +630,6 @@ func ExampleClient_timeseries_aggregation() { _, err := rdb.TSCreateWithArgs(ctx, "rg:2", &redis.TSOptions{ Labels: map[string]string{"location": "us", "unit": "cm"}, }).Result() - if err != nil { panic(err) } @@ -673,7 +641,6 @@ func ExampleClient_timeseries_aggregation() { {"rg:2", 3, 1.9}, {"rg:2", 4, 1.78}, }).Result() - if err != nil { panic(err) } @@ -688,7 +655,6 @@ func ExampleClient_timeseries_aggregation() { BucketDuration: 2, }, ).Result() - if err != nil { panic(err) } @@ -717,7 +683,6 @@ func ExampleClient_timeseries_agg_bucket() { // STEP_START agg_bucket res1, err := rdb.TSCreate(ctx, "sensor3").Result() - if err != nil { panic(err) } @@ -733,7 +698,6 @@ func ExampleClient_timeseries_agg_bucket() { {"sensor3", 60, 6000}, {"sensor3", 70, 7000}, }).Result() - if err != nil { panic(err) } @@ -749,7 +713,6 @@ func ExampleClient_timeseries_agg_bucket() { BucketDuration: 25, }, ).Result() - if err != nil { panic(err) } @@ -768,7 +731,6 @@ func ExampleClient_timeseries_agg_bucket() { Align: "START", }, ).Result() - if err != nil { panic(err) } @@ -802,7 +764,6 @@ func ExampleClient_timeseries_aggmulti() { res37, err := rdb.TSCreateWithArgs(ctx, "wind:1", &redis.TSOptions{ Labels: map[string]string{"country": "uk"}, }).Result() - if err != nil { panic(err) } @@ -812,7 +773,6 @@ func ExampleClient_timeseries_aggmulti() { res38, err := rdb.TSCreateWithArgs(ctx, "wind:2", &redis.TSOptions{ Labels: map[string]string{"country": "uk"}, }).Result() - if err != nil { panic(err) } @@ -822,7 +782,6 @@ func ExampleClient_timeseries_aggmulti() { res39, err := rdb.TSCreateWithArgs(ctx, "wind:3", &redis.TSOptions{ Labels: map[string]string{"country": "us"}, }).Result() - if err != nil { panic(err) } @@ -832,7 +791,6 @@ func ExampleClient_timeseries_aggmulti() { res40, err := rdb.TSCreateWithArgs(ctx, "wind:4", &redis.TSOptions{ Labels: map[string]string{"country": "us"}, }).Result() - if err != nil { panic(err) } @@ -845,7 +803,6 @@ func ExampleClient_timeseries_aggmulti() { {"wind:3", 1, 5}, {"wind:4", 1, 20}, }).Result() - if err != nil { panic(err) } @@ -858,7 +815,6 @@ func ExampleClient_timeseries_aggmulti() { {"wind:3", 2, 4}, {"wind:4", 2, 25}, }).Result() - if err != nil { panic(err) } @@ -871,7 +827,6 @@ func ExampleClient_timeseries_aggmulti() { {"wind:3", 3, 8}, {"wind:4", 3, 18}, }).Result() - if err != nil { panic(err) } @@ -889,7 +844,6 @@ func ExampleClient_timeseries_aggmulti() { Reducer: "max", }, ).Result() - if err != nil { panic(err) } @@ -937,7 +891,6 @@ func ExampleClient_timeseries_aggmulti() { Reducer: "avg", }, ).Result() - if err != nil { panic(err) } @@ -1018,7 +971,6 @@ func ExampleClient_timeseries_compaction() { // STEP_START create_compaction res45, err := rdb.TSCreate(ctx, "hyg:1").Result() - if err != nil { panic(err) } @@ -1026,7 +978,6 @@ func ExampleClient_timeseries_compaction() { fmt.Println(res45) // >>> OK res46, err := rdb.TSCreate(ctx, "hyg:compacted").Result() - if err != nil { panic(err) } @@ -1036,7 +987,6 @@ func ExampleClient_timeseries_compaction() { res47, err := rdb.TSCreateRule( ctx, "hyg:1", "hyg:compacted", redis.Min, 3, ).Result() - if err != nil { panic(err) } @@ -1044,7 +994,6 @@ func ExampleClient_timeseries_compaction() { fmt.Println(res47) // >>> OK res48, err := rdb.TSInfo(ctx, "hyg:1").Result() - if err != nil { panic(err) } @@ -1052,7 +1001,6 @@ func ExampleClient_timeseries_compaction() { fmt.Println(res48["rules"]) // >>> [[hyg:compacted 3 MIN 0]] res49, err := rdb.TSInfo(ctx, "hyg:compacted").Result() - if err != nil { panic(err) } @@ -1066,7 +1014,6 @@ func ExampleClient_timeseries_compaction() { {"hyg:1", 1, 77}, {"hyg:1", 2, 78}, }).Result() - if err != nil { panic(err) } @@ -1076,7 +1023,6 @@ func ExampleClient_timeseries_compaction() { res51, err := rdb.TSRange( ctx, "hyg:compacted", 0, math.MaxInt64, ).Result() - if err != nil { panic(err) } @@ -1084,7 +1030,6 @@ func ExampleClient_timeseries_compaction() { fmt.Println(res51) // >>> [] res52, err := rdb.TSAdd(ctx, "hyg:1", 3, 79).Result() - if err != nil { panic(err) } @@ -1094,7 +1039,6 @@ func ExampleClient_timeseries_compaction() { res53, err := rdb.TSRange( ctx, "hyg:compacted", 0, math.MaxInt64, ).Result() - if err != nil { panic(err) } @@ -1137,7 +1081,6 @@ func ExampleClient_timeseries_delete() { // STEP_START del res54, err := rdb.TSInfo(ctx, "thermometer:1").Result() - if err != nil { panic(err) } @@ -1147,7 +1090,6 @@ func ExampleClient_timeseries_delete() { fmt.Println(res54["lastTimestamp"]) // >>> 2 res55, err := rdb.TSAdd(ctx, "thermometer:1", 3, 9.7).Result() - if err != nil { panic(err) } @@ -1155,7 +1097,6 @@ func ExampleClient_timeseries_delete() { fmt.Println(res55) // >>> 3 res56, err := rdb.TSInfo(ctx, "thermometer:1").Result() - if err != nil { panic(err) } @@ -1165,7 +1106,6 @@ func ExampleClient_timeseries_delete() { fmt.Println(res56["lastTimestamp"]) // >>> 3 res57, err := rdb.TSDel(ctx, "thermometer:1", 1, 2).Result() - if err != nil { panic(err) } @@ -1173,7 +1113,6 @@ func ExampleClient_timeseries_delete() { fmt.Println(res57) // >>> 2 res58, err := rdb.TSInfo(ctx, "thermometer:1").Result() - if err != nil { panic(err) } @@ -1183,7 +1122,6 @@ func ExampleClient_timeseries_delete() { fmt.Println(res58["lastTimestamp"]) // >>> 3 res59, err := rdb.TSDel(ctx, "thermometer:1", 3, 3).Result() - if err != nil { panic(err) } @@ -1191,7 +1129,6 @@ func ExampleClient_timeseries_delete() { fmt.Println(res59) // >>> 1 res60, err := rdb.TSInfo(ctx, "thermometer:1").Result() - if err != nil { panic(err) } From 953a1edd7c34487f842d0cce4c17e8dff3d9fbb4 Mon Sep 17 00:00:00 2001 From: Andy Stark Date: Thu, 31 Jul 2025 16:47:39 +0100 Subject: [PATCH 5/5] DOC-5472 fixed param formatting, following feedback --- doctests/timeseries_tut_test.go | 40 ++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/doctests/timeseries_tut_test.go b/doctests/timeseries_tut_test.go index d779f6827..28e163539 100644 --- a/doctests/timeseries_tut_test.go +++ b/doctests/timeseries_tut_test.go @@ -57,7 +57,8 @@ func ExampleClient_timeseries_create() { res4, err := rdb.TSAddWithArgs( ctx, "thermometer:2", - 1, 10.8, + 1, + 10.8, &redis.TSOptions{ Retention: 100, }, @@ -80,7 +81,8 @@ func ExampleClient_timeseries_create() { res6, err := rdb.TSAddWithArgs( ctx, "thermometer:3", - 1, 10.4, + 1, + 10.4, &redis.TSOptions{ Labels: map[string]string{ "location": "UK", @@ -200,9 +202,7 @@ func ExampleClient_timeseries_range() { // Retrieve all the data points in ascending order. // Note: use 0 and `math.MaxInt64` instead of - and + // to denote the minimum and maximum possible timestamps. - res3, err := rdb.TSRange(ctx, "rg:1", - 0, math.MaxInt64, - ).Result() + res3, err := rdb.TSRange(ctx, "rg:1", 0, math.MaxInt64).Result() if err != nil { panic(err) } @@ -252,7 +252,8 @@ func ExampleClient_timeseries_range() { res8, err := rdb.TSRangeWithArgs( ctx, "rg:1", - 0, math.MaxInt64, + 0, + math.MaxInt64, &redis.TSRangeOptions{ FilterByTS: []int{0, 2, 4}, }, @@ -266,7 +267,8 @@ func ExampleClient_timeseries_range() { res9, err := rdb.TSRevRangeWithArgs( ctx, "rg:1", - 0, math.MaxInt64, + 0, + math.MaxInt64, &redis.TSRevRangeOptions{ FilterByTS: []int{0, 2, 4}, FilterByValue: []int{20, 25}, @@ -281,7 +283,8 @@ func ExampleClient_timeseries_range() { res10, err := rdb.TSRevRangeWithArgs( ctx, "rg:1", - 0, math.MaxInt64, + 0, + math.MaxInt64, &redis.TSRevRangeOptions{ FilterByTS: []int{0, 2, 4}, FilterByValue: []int{22, 22}, @@ -491,7 +494,8 @@ func ExampleClient_timeseries_query_multi() { // specify any aggregators. res30, err := rdb.TSMRangeWithArgs( ctx, - 0, 2, + 0, + 2, []string{"unit=mm"}, &redis.TSMRangeOptions{ WithLabels: true, @@ -535,7 +539,8 @@ func ExampleClient_timeseries_query_multi() { // in descending order of timestamp. res31, err := rdb.TSMRevRangeWithArgs( ctx, - 1, 3, + 1, + 3, []string{"unit=(cm,mm)"}, &redis.TSMRevRangeOptions{ SelectedLabels: []interface{}{"location"}, @@ -649,7 +654,8 @@ func ExampleClient_timeseries_aggregation() { res32, err := rdb.TSRangeWithArgs( ctx, "rg:2", - 0, math.MaxInt64, + 0, + math.MaxInt64, &redis.TSRangeOptions{ Aggregator: redis.Avg, BucketDuration: 2, @@ -707,7 +713,8 @@ func ExampleClient_timeseries_agg_bucket() { res3, err := rdb.TSRangeWithArgs( ctx, "sensor3", - 10, 70, + 10, + 70, &redis.TSRangeOptions{ Aggregator: redis.Min, BucketDuration: 25, @@ -724,7 +731,8 @@ func ExampleClient_timeseries_agg_bucket() { res4, err := rdb.TSRangeWithArgs( ctx, "sensor3", - 10, 70, + 10, + 70, &redis.TSRangeOptions{ Aggregator: redis.Min, BucketDuration: 25, @@ -837,7 +845,8 @@ func ExampleClient_timeseries_aggmulti() { // for the country at that timestamp. res44, err := rdb.TSMRangeWithArgs( ctx, - 0, math.MaxInt64, + 0, + math.MaxInt64, []string{"country=(us,uk)"}, &redis.TSMRangeOptions{ GroupByLabel: "country", @@ -884,7 +893,8 @@ func ExampleClient_timeseries_aggmulti() { // for the country at that timestamp. res45, err := rdb.TSMRangeWithArgs( ctx, - 0, math.MaxInt64, + 0, + math.MaxInt64, []string{"country=(us,uk)"}, &redis.TSMRangeOptions{ GroupByLabel: "country",