I have a two structure:
type GoogleAccount struct {
Id uint64
Token string
}
It represent my custom PostgreSQL object type (i created myself):
CREATE TYPE GOOGLE_ACCOUNT AS
(
id NUMERIC,
token TEXT
);
And next structure is table in DB:
type Client struct {
IdClient uint64 `gorm:"primary_key"`
Name string
PhotoUrl string
ApprovalNumber uint16
Phone string
Password string
HoursOfNotice int8
Google GoogleAccount
}
And my custom object nested in type Client and named as google
. I've tried to read data by the next way:
var users model.Client
db.First(&users)
But unfortunately I can't read field google
(have a default value). I don't want to create separate table with google_account, or make this structure as separated fields in client table or packed it as json (created separate entity, because this structure used not only in this table and I'm searching new ways, that get the same result, but more gracefully). The task is not to simplify the presentation of data in the table. I need to make the correct mapping of the object from postgres to the entity.
Right now I found one solution - implement Scanner to GoogleAccount. But value in the input method is []uint8. As I can suppose, []uint8 can cast to string, and after that I can parse this string. This string (that keep in db) look like (x,x)
- where x - is value. Is the right way, to parse string and set value to object? Or is way to get this result by ORM?
Is the possible way, to read this data as nested structure object?
It looks like you'll want to do two things with what you have: (1) update the model so you have the right relationship binding, and (2) use the .Preload()
method if you're trying to get it to associate the data on read.
Model Changes
Gorm automatically infers relationships based on the name of the attributes in your struct and the name of the referenced struct. The problem is that Google
attribute of type GoogleAccount
isn't associating because gorm is looking for a type Google struct
.
You're also missing a foreign key on GoogleAccount
. How would the ORM know which GoogleAccount
to associate with which Client
? You should add a ClientId
to your GoogleAccount
struct definition.
Also, I would change the primary keys you're using to type uint
since that's what gorm defaults to (unless you have a good reason not to use it)
If I were you, I would change my struct definitions to the following:
type Client struct {
IdClient uint `gorm:"primary_key"`
Name string
PhotoUrl string
ApprovalNumber uint16
Phone string
Password string
HoursOfNotice int8
GoogleAccount GoogleAccount // Change this to `GoogleAccount`, the same name of your struct
}
type GoogleAccount struct {
Id uint
ClientId uint // Foreign key
Token string
}
For more information on this, take a look at the associations documentation here: http://gorm.io/associations.html#has-one
Preloading associations
Now that you actually have them properly related, you can .Preload()
get the nested object you want:
db.Preload("GoogleAccount").First(&user)
Using .Preload()
will populate the user.GoogleAccount
attribute with the correctly associated GoogleAccount
based on the ClientId
.
For more information on this, take a look at the preloading documentation: http://gorm.io/crud.html#preloading-eager-loading
Right now I found one solution - implement Scanner to GoogleAccount
. At input of the Scan
method I got []uint8
, that I cast to string and parse in the end. This string (that keeping in db) look like (x,x)
- where x
- is value. Of course, it is not correct way to achieve my goal. But I couldn't found other solution.
I highly recommended use classical binding by relationship or simple keeping these fields in table as simplest value (not as object).
But if you would like to experiment with nested object in table, you can look at my realization, maybe it would be useful for you: https://github.com/kirikzyusko1996/go-cleaning-api/blob/master/src/app/model/client.go