-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Add redis.Scan() to scan results from redis maps into structs. #1631
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
👍 I've left some comments - hopefully it is not too much :) Also please set "Allow edits from maintainers" on the PR so I can add commits... Let's move the code to |
The package uses reflection to decode default types (int, string etc.) from Redis map results (key-value pair sequences) into struct fields where the fields are matched to Redis keys by tags. Similar to how `encoding/json` allows custom decoders using `UnmarshalJSON()`, the package supports decoding of arbitrary types into struct fields by defining a `Decode(string) error` function on types. The field/type spec of every struct that's passed to Scan() is cached in the package so that subsequent scans avoid iteration and reflection of the struct's fields.
Incorporated all the changes you suggested and moved the package to PS: Did a force push because it was mostly hygiene fixes. |
@knadh I've pushed few small changes, but this looks good already. Could you add |
Yep, will push this. |
Added here: a4144ea |
tag := f.Tag.Get(fieldTag) | ||
if tag == "" || tag == "-" { | ||
continue | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks we are ignoring fields that don't have redis:"something"
tag. Is that intentional?
Usually we are supposed to generate default name from Go field name and only ignore the field when redis:"-"
. What do you think?
https://pkg.go.dev/github.com/codemodus/kace could be used to generate default name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this parser is too simple....can only do the most basic work, it needs to continue to improve its functions,
i can continue to improve it this week,,,if needed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks we are ignoring fields that don't have redis:"something" tag. Is that intentional?
Yeah. Explicitly defining what's to be scanned is better (fewer gotchas) in my opinion. Opting in rather than opting out with "-"
.
this parser is too simple....can only do the most basic work, it needs to continue to improve its functions,
It only handles primitive types. The right way to extend it with the Decode()
interface which was in the original PR. I hope @vmihailenco has plans to introduce that functionality soon!
Could you add one end-to-end test or maybe even an example? That will help people to get started rdb.HSet(..)
rdb.HSet(...)
rdb.HGetAll(ctx, "key").Scan(&dst) |
I just realised, |
@knadh I've pushed a change with |
Float float32 `redis:"float"` | ||
Bool bool `redis:"bool"` | ||
} | ||
var d2 data2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just FYI this can be written as
var d2 struct {
String string `redis:"string"`
Bytes []byte `redis:"byte"`
Int int `redis:"int"`
Uint uint `redis:"uint"`
Float float32 `redis:"float"`
Bool bool `redis:"bool"`
}
missing test for redis 127.0.0.1:6379>> set key 1234567890123456789 type Temp struct {
Key int64 `redis:"key"`
}
|
Added test https://github.com/knadh/redis/commit/f8a546b4820de9e52fe0d244e24dca155688abef. @monkey92t I guess you could add platform specific parsing.
@vmihailenco looks fine. Please go ahead. |
🥳 |
Hello @vmihailenco @knadh What if in this case I have a slice like I see that in the code you check for I need it to be a slice since the result I'm getting from Any ideias on what I'm doing wrong? |
under normal circumstances, the data format of redis is as follows: 127.0.0.1:6379>>set id 100
127.0.0.1:6379>>set name monkey
127.0.0.1:6379>>set age 20
127.0.0.1:6379>>mget id name age
//{"id": 100, "name": "monkey", "age": 20}
//golang
type Per struct {
ID int `redis:"id"`
Name string `redis:"name"`
Age int `redis:"age"`
}
p := &Per{}
err := redis.Mget(ctx, "id", "name", "age").Scan(p)
// p.ID = 100
// p.Name = monkey
// p.Age = 20 i don’t know what you mean by |
I have hundreds of keys like The response from MGet is something like this:
I'm a little lost here on what I have to do :') |
I resolved it by doing the following: res := Cli.MGet(ctx, keys...)
var prices []models.Price
str := fmt.Sprintf("%+v", res.Val())
rawIn := json.RawMessage(str)
bytes, err := rawIn.MarshalJSON()
json.Unmarshal(bytes, &prices) Thanks! |
@mdelclaro The |
Scan doesn’t seem to work on nested structures: #1806. Based on the comments in this PR, it seems that “the package supports decoding of arbitrary |
Decoding |
cannot scan redis.result 2021-12-28T11:31:45.611441+08:00 into struct field UpdatedAt of type time.Time, error-redis.Scan(unsupported time.Time) Hi guys, when scan will support time.Time? |
The issue with |
ping, |
Add Scanner interface, See #2317 |
The package uses reflection to decode default types (int, string etc.) from Redis map results (key-value pair sequences) into
struct fields where the fields are matched to Redis keys by tags.
Similar to how
encoding/json
allows custom decoders usingUnmarshalJSON()
, the package supports decoding of arbitrarytypes into struct fields by defining a
Decode(string) error
function on types.The field/type spec of every struct that's passed to Scan() is cached in the package so that subsequent scans avoid iteration
and reflection of the struct's fields.
Issue: #1603