How to insert a slice into Redis database using Redix.v3 - go

Getting an error while inserting a slice into Redis database using redix.v3. What's redis command to insert a slice? SET or HMSET?
My code:
type Domain struct {
ID string `json:"ID,omitempty"`
ParentID string `json:"parentID,omitempty"`
ParentType string `json:"parentType,omitempty"`
Owner string `json:"owner,omitempty"`
PATEnabled string `json:"PATEnabled,omitempty"`
Name string `json:"name,omitempty"`
}
for _, domain := range domains {
if err := client.Do(radix.FlatCmd(nil, "HMSET", domain.ID, domain)); err != nil {
log.Println(err)
}
Error message:
could not marshal value of type Domain

Related

Extracting Data From Kafka REST Proxy in Go

I am using the REST proxy instance of Kafka for producing and consuming messages.Using the API to get new messages but I am not able to convert those messages to a struct model in Go. For example:
// Get records
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf(FETCH_CONSUMER, URL, GROUP, CONSUMER), nil)
if err != nil {
panic(err)
}
req.Header.Add("Accept", CONTENT_TYPE)
respRecords, err := client.Do(req)
if err != nil {
panic(err)
}
defer respRecords.Body.Close()
fmt.Printf("Response %s\n", respRecords.Status)
fmt.Println(respRecords.Body)
recordsBodyResp := bufio.NewScanner(respRecords.Body)
for recordsBodyResp.Scan() {
fmt.Printf("<--Body %s\n", recordsBodyResp.Text())
}
The value returned is in the following format:
[{"topic":"backward","key":null,"value":{"AdoptionID":"abcd123","IPAddress":"8.8.8.8","Port":"80","Status":"requested"},"partition":0,"offset":7}]
Since it's an array of objects, I want to extract the value portion of the key "value" into a struct.
That is where I am stuck.
You can create a struct like:
type AutoGenerated []struct {
Topic string `json:"topic"`
Key interface{} `json:"key"`
Value Value `json:"value"`
Partition int `json:"partition"`
Offset int `json:"offset"`
}
type Value struct {
AdoptionID string `json:"AdoptionID"`
IPAddress string `json:"IPAddress"`
Port string `json:"Port"`
Status string `json:"Status"`
}
And Unmarshal in that struct.
See this sample code:
package main
import (
"fmt"
"encoding/json"
)
func main() {
type Value struct {
AdoptionID string `json:"AdoptionID"`
IPAddress string `json:"IPAddress"`
Port string `json:"Port"`
Status string `json:"Status"`
}
type AutoGenerated []struct {
Topic string `json:"topic"`
Key interface{} `json:"key"`
Value Value `json:"value"`
Partition int `json:"partition"`
Offset int `json:"offset"`
}
byt := []byte(`[{"topic":"backward","key":null,"value":{"AdoptionID":"abcd123","IPAddress":"8.8.8.8","Port":"80","Status":"requested"},"partition":0,"offset":7}]`)
var dat AutoGenerated
if err := json.Unmarshal(byt, &dat); err != nil {
panic(err)
}
fmt.Printf("%#v", dat)
}

How do I parse the password as a byte array with fiber

I am using Go fiber's body parser to parse the request body. I have the following struct
type SignInCredentials struct {
Email string
Password []byte
}
Where I have a Password as a slice of bytes. When I try to parse the body like so
func SignUp(db *database.Database) fiber.Handler {
return func(c *fiber.Ctx) error {
cred := new(model.SignUpCredentials)
if err := c.BodyParser(cred); err != nil {
return SendParsingError(c)
}
I get a schema error
schema: error converting value for index 0 of \"Password\
because the type of the form data password doesn't match the []byte type. I looked at their examples and I noticed that in the documentation they use a string to store the password. But I am set on storing it as a slice of bytes. How can I do this?
// Field names should start with an uppercase letter
type Person struct {
Name string `json:"name" xml:"name" form:"name"`
Pass string `json:"pass" xml:"pass" form:"pass"`
}
app.Post("/", func(c *fiber.Ctx) error {
p := new(Person)
if err := c.BodyParser(p); err != nil {
return err
}
log.Println(p.Name) // john
log.Println(p.Pass) // doe
// ...
})
It is transmitted as a string, not []byte. You need to parse it as a string first, then you can transform it into the structure you want:
func SignUp(db *database.Database) fiber.Handler {
return func(c *fiber.Ctx) error {
// an anonymous struct to parse the body
body := struct{
Email string
Password string
}{}
if err := c.BodyParser(body); err != nil {
return SendParsingError(c)
}
cred := SignInCredentials{
Email: body.Email,
Password: []byte(body.Password),
}

Reuse or cast structs for validation, API results, and DB saves in Go

I'm trying to write an API that will do different things with the data depending on its purpose.
API results - The API should expose certain fields to the user
Validation - Validation should handle different schemas e.g. login form doesn't require Name, but register does
Database - The database should save everything, including password etc. - if I try using the same struct for the API and DB with json:"-" or un-exporting the field the database save also ignores the field
Some sample code is below with a couple of comments in capitals to show where I ideally need to type cast to change the data. As they are different structs, they cannot be type cast, so I get an error. How can I fix this?
Alternatively, what is a better way of doing different things with the data without having lots of similar structs?
// IDValidation for uuids
type IDValidation struct {
ID string `json:"id" validate:"required,uuid"`
}
// RegisterValidation for register form
type RegisterValidation struct {
Name string `json:"name" validate:"required"`
Email string `json:"email" validate:"required,email"`
Password string `json:"password" validate:"required,min=8"`
}
// UserModel to save in DB
type UserModel struct {
ID string `json:"id,omitempty"`
Name string `json:"name"`
Email string `json:"email"`
Password string `json:"password,omitempty"`
Active bool `json:"active,omitempty"`
CreatedAt int64 `json:"created_at,omitempty"`
UpdatedAt int64 `json:"updated_at,omitempty"`
jwt.StandardClaims
}
// UserAPI data to display to user
type UserAPI struct {
ID string `json:"id,omitempty"`
Name string `json:"name"`
Email string `json:"email"`
Active bool `json:"active,omitempty"`
}
// register a user
func register(c echo.Context) error {
u := new(UserModel)
if err := c.Bind(u); err != nil {
return err
}
// NEED TO CAST TO RegisterValidation HERE?
if err := c.Validate(u); err != nil {
return err
}
token, err := u.Register()
if err != nil {
return err
}
return c.JSON(http.StatusOK, lib.JSON{"token": token})
}
// retrieve a user
func retrieve(c echo.Context) error {
u := IDValidation{
ID: c.Param("id"),
}
if err := c.Validate(u); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
}
// NEED TO CAST USER TO UserAPI?
user, err := userModel.GetByID(u.ID)
if err != nil {
return err
}
return c.JSON(200, lib.JSON{"message": "User found", "user": user})
}

GORM Associations

Given the following data structure which has been created in the database and there is valid data in the rows in the appropriate tables:-
type Deployment struct {
gorm.Model
Name string `gorm:"unique_index:idx_name"`
RestAPIUser string
RestAPIPass string
Servers []Server
model *Model
}
type Server struct {
gorm.Model
DeploymentID uint
Hostname string `gorm:"unique_index:idx_hostname"`
RestPort string
Version string
}
I'm trying to select all Deployments and have GORM automatically fill the Servers for each Deployment.
Unfortunately, it doesn't do this. I've tried several variations of using the Associations() func but I can't seem to get it to work. I seem to have to do this manually:-
func (m *Model) GetDeployments() ([]Deployment, error) {
deployments := []Deployment{}
err := m.db.Find(&deployments).Error
if err != nil {
return nil, err
}
deploymentsWithServers := []Deployment{}
for _, d := range deployments {
servers := []Server{}
err := m.db.Model(&d).Association("Servers").Find(&servers).Error
if err != nil {
return nil, err
}
d.Servers = servers
deploymentsWithServers = append(deploymentsWithServers, d)
}
return deploymentsWithServers, nil
}
Does anyone have any suggestions how I can get GORM to fill the Servers field automatically? Thanks!
Try
m.db.Preload("Servers").Find(&Deployment{})

Golang DRY for nested structs

I have a BaseEntity struct and one method with *BaseEntity receiver that parses xml from file
type BaseEntity struct {
FilePath string
Collection string
}
func (this *BaseEntity) Parse() *[]byte {
xmlFile, err := ioutil.ReadFile(this.FilePath)
if err != nil {
fmt.Println("Error opening file:", err)
return nil
}
return &xmlFile
}
I also have several structs where BaseEntity is embedded, for eg. Users, Posts, Comments, Tags ... etc
type Users struct {
Data []User `xml:"row"`
BaseEntity
}
type User struct {
WebsiteUrl string `xml:"WebsiteUrl,attr"`
UpVotes string `xml:"UpVotes,attr"`
Id string `xml:"Id,attr"`
Age string `xml:"Age,attr"`
DisplayName string `xml:"DisplayName,attr"`
AboutMe string `xml:"AboutMe,attr"`
Reputation string `xml:"Reputation,attr"`
LastAccessDate string `xml:"LastAccessDate,attr"`
DownVotes string `xml:"DownVotes,attr"`
AccountId string `xml:"AccountId,attr"`
Location string `xml:"Location,attr"`
Views string `xml:"Views,attr"`
CreationDate string `xml:"CreationDate,attr"`
ProfileImageUrl string `xml:"ProfileImageUrl,attr"`
}
func (this *Users) LoadDataToDB() {
file := this.Parse()
xml.Unmarshal(*file, &this)
// Init db
db := database.MgoDb{}
db.Init()
defer db.Close()
for _, row := range this.Data {
err := db.C(this.Collection).Insert(&row)
if err != nil {
fmt.Println(err)
}
}
}
And for each of these structs I need to create a method LoadDataToDB that loads data in db and has some code.
This method can't have *BaseEntity receiver because I can't get this.Data in base struct and I can't get this struct from parameters because it always a different struct.
How to DRY and move this repeating method from every embedded struct to one?

Resources