From 45cd930be25c21697142e6d554c0376fb4409f02 Mon Sep 17 00:00:00 2001 From: qishenonly <1050026498@qq.com> Date: Wed, 5 Jul 2023 18:30:46 +0800 Subject: [PATCH] feat: new method--HIncrByFloat(#136) --- structure/hash.go | 61 ++++++++++++++++++++++++++++++++++++++++++ structure/hash_test.go | 33 +++++++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/structure/hash.go b/structure/hash.go index 698b3895..80f982a0 100644 --- a/structure/hash.go +++ b/structure/hash.go @@ -494,3 +494,64 @@ func (hs *HashStructure) HIncrBy(key, field []byte, increment int64) (int64, err return val, nil } + +// HIncrByFloat increments the float value of a hash field by the given number. +func (hs *HashStructure) HIncrByFloat(key, field []byte, increment float64) (float64, error) { + // Check the parameters + if len(key) == 0 || len(field) == 0 { + return 0, _const.ErrKeyIsEmpty + } + + // Find the hash metadata by the given key + hashMeta, err := hs.findHashMeta(key, Hash) + if err != nil { + return 0, err + } + + // If the counter is 0, return 0 + if hashMeta.counter == 0 { + return 0, nil + } + + // Create a new HashField + hf := &HashField{ + field: field, + key: key, + version: hashMeta.version, + } + + // Encode the HashField + hfBuf := hf.encodeHashField() + + // Get the field from the database + value, err := hs.db.Get(hfBuf) + if err != nil && err == _const.ErrKeyNotFound { + return 0, nil + } + + // Convert the value to float64 + val, err := strconv.ParseFloat(string(value), 64) + if err != nil { + return 0, err + } + + // Add the increment to the value + val += increment + + // Convert the value to string + value = []byte(strconv.FormatFloat(val, 'f', -1, 64)) + + // new a write batch + batch := hs.db.NewWriteBatch(config.DefaultWriteBatchOptions) + + // Put the field to the database + _ = batch.Put(hfBuf, value) + + // Commit the write batch + err = batch.Commit() + if err != nil { + return 0, err + } + + return val, nil +} diff --git a/structure/hash_test.go b/structure/hash_test.go index 78051c94..ff7e31c9 100644 --- a/structure/hash_test.go +++ b/structure/hash_test.go @@ -175,3 +175,36 @@ func TestHashStructure_HIncrBy(t *testing.T) { assert.Equal(t, v4, int64(0)) } + +func TestHashStructure_HIncrByFloat(t *testing.T) { + hash := initHashDB() + + ok1, err := hash.HSet(randkv.GetTestKey(1), []byte("field1"), []byte("10")) + assert.Nil(t, err) + assert.True(t, ok1) + + ok2, err := hash.HSet(randkv.GetTestKey(1), []byte("field2"), []byte("10")) + assert.Nil(t, err) + assert.True(t, ok2) + + ok3, err := hash.HSet(randkv.GetTestKey(1), []byte("field3"), []byte("10")) + assert.Nil(t, err) + assert.True(t, ok3) + + v1, err := hash.HIncrByFloat(randkv.GetTestKey(1), []byte("field1"), 1.1) + assert.Nil(t, err) + assert.Equal(t, v1, float64(11.1)) + + v2, err := hash.HIncrByFloat(randkv.GetTestKey(1), []byte("field2"), -1.1) + assert.Nil(t, err) + assert.Equal(t, v2, float64(8.9)) + + v3, err := hash.HIncrByFloat(randkv.GetTestKey(1), []byte("field3"), 0) + assert.Nil(t, err) + assert.Equal(t, v3, float64(10)) + + v4, err := hash.HIncrByFloat(randkv.GetTestKey(1), []byte("field4"), 1.1) + assert.Nil(t, err) + assert.Equal(t, v4, float64(0)) + +}