gorm primary key dont appear in database - database

im a beginner in golang. when im using gorm:"primaryKey"
i dont see any field that use primary key
this is my model
type Orders struct {
OrderID uint64 `gorm:"primaryKey" json:"orderId"`
CustomerName string `json:"customerName"`
OrderedAt time.Time `json:"orderedAt" example:"2020-01-09T21:21:46+00:00"`
Items []Items `json:"items"`
}
type Items struct {
ItemID uint64 `gorm:"primaryKey" json:"lineItemId"`
Item_code string `json:"itemCode"`
Description string `json:"description"`
Quantity int `json:"quantity"`
}
which part do i wrong?
and do i need relational database for items field?

Lets be clear over here,
At first you need to declare a struct as a Model i.e by
type Anything struct {
gorm.Model
... (other fields)
}
And then in order to use Has Many relation you need to use the ID of the parent on the child i.e
type User struct {
gorm.Model
CreditCards []CreditCard
}
type CreditCard struct {
gorm.Model
Number string
UserID uint (like this over here.)
}
Please do kindly follow the docs GORM Docs

In the model Orders model has a hasMany relation to Items, but Items is missing the Key of Orders.
The db.AutoMigrate(&models.Orders{}, &models.Items{}) should be failing to create in this case for Order.Items, but the error is ignored.
Include OrdersID in Items struct to complete referential integrity because gorm expects default primary key/ foreign key as <StructName>ID so for Orders it will search OrdersID in Items
type Orders struct {
OrdersID uint64 `gorm:"primaryKey" json:"orderId"`
...
}
type Items struct {
OrdersID uint64
...
}
Suggestion, structs should be called Order and Item rather than Orders and Items thus the model becomes
type Order struct {
OrderID uint64 `gorm:"primaryKey" json:"orderId"`
CustomerName string `json:"customerName"`
OrderedAt time.Time `json:"orderedAt" example:"2020-01-09T21:21:46+00:00"`
Items []Item `json:"items"`
}
type Item struct {
ItemID uint64 `gorm:"primaryKey" json:"lineItemId"`
Item_code string `json:"itemCode"`
Description string `json:"description"`
Quantity int `json:"quantity"`
OrderID uint64
}

Related

Go Gorm: Foreign key not present in table creation

I'm working on a Gin app using Gorm ORM (I'm new to both of them). I've got the following model:
type Record struct {
Barcode string `json:"barcode" gorm:"size:48;unique;not null" sql:"index"`
Name string `json:"name" gorm:"size:160;unique;not null"`
Artist Artist `gorm:"foreignKey:ArtistID""`
ArtistId uint
Category Category `gorm:"foreignKey:CategoryID"`
CategoryId uint
NumOfRecords int `json:"num_of_records" gorm:"not null"`
OriginalReleaseDate time.Time `json:"original_release_date" gorm:"default:null"`
ReissueReleaseDate time.Time `json:"reissue_release_date" gorm:"default:null"`
SideColor string `json:"side_color" gorm:"default:null"`
BarcodeInRecord bool `json:"barcode_in_record" gorm:"default=true"`
gorm.Model
}
As you can see there are two fields with two foreign keys: Artist and Category.
Here's those models:
type Category struct {
Name string `json:"name" gorm:"size:60;unique;not null"`
Description string `json:"description" gorm:"size:120"`
Parent uint `json:"parent" gorm:"default:null"`
Active bool `json:"active" gorm:"default:true"`
gorm.Model
}
type Artist struct {
Name string `json:"name" gorm:"size:120;unique;not null"`
Type string `json:"type" gorm:"default:null"`
CountryOfOrigin string `json:"countryOfOrigin" gorm:"default:null"`
gorm.Model
}
category_id and artist_id columns are being created but they are not referencing the other tables two tables:
I've tried to define those fields using AssociationForeignKey:Refer. I also tried to change the foreign key name to simply ID since that's the name that GORM assigns to primary keys but none of those thinks have worked.
What am I missing?
IMO Gorm docs are pretty lousy. From another SO question (Gorm Golang orm associations) it is said that:
it doesn't (create FKs when migrations run). If you want Foreign Key in DB, you need explicitly write something like db.Model(&Place{}).AddForeignKey("town_id", "towns(id)", "RESTRICT", "RESTRICT") during your migrations.

Fetching a struct and other data in one query

I have the following table schema:
user
-----
id uuid
name string
user_model
------
id uuid
user_id uuid
model_id uuid
role int
model
_____
id uuid
name string
model_no string
I have the following code which fetches the data from the "model" table.
underlyingModel = &model{}
var model IModel
model = underlyingModel
role := 0
db.Table("model").Joins('INNER JOIN user_model ON user.id = user_model.uuid')
.Joins('INNER JOIN model ON user.id = model_id').Find(&model);
In my actual code, the model can be many different struct types with different fields, they're all behind the IModel interface.
What I want to do is to fetch that extra role field from the user_model in one query. Something like .Find(&model, &role).
Is it possible using Gorm?
One possible solution is to create an anonymous struct to put the results in, with a combination of the Select() method.
var selectModel struct {
ID string //I'm assuming uuid matches the string
Name string
ModelNo string
Role int
}
db.Table("model").
Joins("INNER JOIN user_model ON user.id = user_model.uuid").
Joins("INNER JOIN model ON user.id = model_id").
Select("model.id, model.name, model.model_no, user_model.role").
Find(&selectModel);
Basically, you create an anonymous struct with selectModel variable, containing all the fields you want to return. Then, you need to do a select statement because you need some fields that are not part of the model table.
Here you can find more info on Smart Select Fields in form.
EDIT:
Based on additional info from the comments, there is a solution that might work.
Your IModel interface could have two methods in its signature, one to extract a string for the SELECT part of the SQL query, and the other one to get a pointer of the selectModel that you would use in the Find method.
type IModel interface {
SelectFields() string
GetSelectModel() interface{}
}
The implementation would go something like this:
func (m *model) SelectFields() string {
return "model.id, model.name, model.model_no, user_model.role"
}
func (m *model) GetSelectModel() interface{} {
return &m.selectModel
}
type model struct {
selectModel
ID uint64
Age int
}
type selectModel struct {
Name string
Email string
}
Then, your query could look something like this:
var m IModel
m = model{}
db.Table("model").
Joins("INNER JOIN user_model ON user.id = user_model.uuid").
Joins("INNER JOIN model ON user.id = model_id").
Select(m.GetSelectFields()).
Find(m.GetSelectModel());

Decimal type in Go and Postgresql with gorm

So i'm creating an API and I needed to store the price of something.
I'm using gorm and gormigrate for my database migration.
I'm just wondering what proper type should I use for storing decimals. I've red somewhere that I shouldn't use floats when storing currencies.
type MyStruct struct {
Name string `json:"name" gorm:"not null"`
Description string `json:"description" gorm:"null"`
Price <what type should be here> `json:"price"`
}
So, based on the suggestion of #ain, I used shopspring/decimal. But it's giving me an error when I do automigrate.
It turns out that I only needed to set the type to numeric using a gorm tag to make it work:
type MyStruct struct {
Name string `json:"name" gorm:"not null"`
Description string `json:"description" gorm:"null"`
Price decimal.Decimal `json:"price" gorm:"type:numeric"`
}

Go App Engine nested objects are not stored in Cloud Datastore

I have a entity EmergencyCase that has 2 embedded structs (1 array and 1 struct)
When I try to save the EmergencyCase by calling:
datastore.Put(c, key, &ec)
Everything is stored fine except the Pos field (type Position). There is no error or log entry about this. It is just not stored. Any suggestions?
Here are my 3 entities definitions:
type Position struct{
lon float32
lat float32
}
type EmergencyCase struct{
// Autogenerated id, not stored in the database.
ID string `datastore:"-"`
CreatedAt time.Time
Closed bool
ClosedByUser bool `datastore:",noindex"`
AutoClosed bool `datastore:",noindex"`
Pos Position
Events []Event
}
type Event struct{
// Autogenerated id, not stored in the datastore.
ID string `datastore:"-"`
CreatedAt time.Time
Name string `datastore:",noindex"`
}
Export the Position field names by uppercasing the first letter in the name. The datastore stores exported fields only.
type Position struct{
Lon float32
Lat float32
}
Try using appengine.GeoPoint as an altenative/optimised class

Querying an array using Go and Datastore

I have the following scenario:
type Band struct {
Name string
LocationId *datastore.Key
Albums []Album
}
type Album struct {
Name string
GenreId *datastore.Key
Year int
}
What I want to do is query a Bands Albums key for an album with a specific GenreId key.
I found the answer. It turned out to be simple. Instead of
Filter("GenreId =", genreId)
I used
Filter("Albums.GenreId =", genreId)
That gave me valid query results.

Resources