One-one relationship with different table namesin Gorm - go

I have the following tables.
nyct2010
and
trips
The models I have defined are below.
type Nyct2010 struct {
Id int `gorm:"column:gid"`
Borocode int
}
type Trip struct {
Id int
PickupLongitude float64 `gorm:"column:pickup_longitude"`
PickupLatitude float64 `gorm:"column:pickup_latitude"`
DropoffLongitude float64 `gorm:"column:dropoff_longitude"`
DropoffLatitude float64 `gorm:"column:dropoff_latitude"`
PickupTime time.Time `gorm:"column:pickup_datetime"`
DropoffTime time.Time `gorm:"column:dropoff_datetime"`
Fare float64 `gorm:"column:fare_amount"`
Tip float64 `gorm:"column:tip_amount"`
Total float64 `gorm:"column:total_amount"`
PaymentType string `gorm:"column:payment_type"`
Tax float64 `gorm:"column:mta_tax"`
Nyct2010 Nyct2010
Nyct2010Id int `gorm:"column:pickup_nyct2010_gid"`
}
I am trying to get the related entry from nyct2010. It is related to pickup_nyc2010_gid.
var trip Trip
db.First(&trip, 2112111736)
db.Model(trip).Related(&trip.Nyct2010)
The above code produces the following debug messages.
[2016-01-15 12:34:04] [160.31ms] SELECT * FROM "trips" WHERE ("id" = '2112111736') ORDER BY "trips"."id" ASC LIMIT 1
[2016-01-15 12:34:04] pq: zero-length delimited identifier at or near """"
[2016-01-15 12:34:04] [77.29ms] SELECT * FROM "nyct2010" WHERE ("" = '1475')
[2016-01-15 12:34:04] pq: zero-length delimited identifier at or near """"
For some reason gorm is ignoring the field that I am mapping Nyct2010.Id to, I am trying to map it to Nyct2010.gid.
Am I going about this wrong or is this an error with Gorm?

Try this:
type Nyct2010 struct {
ID uint `gorm:"primary_key column:gid"`
Borocode int
}
var trip Trip
var nyct2010 Nyct2010
db.First(&trip, 2112111736)
db.Model(&trip).Related(&nyct2010,"pickup_nyct2010_gid")

Related

Issue with nested struct in Go

I have two structs A & B and a nested struct C with A & B, defined as below:
Struct A :
type Source_a struct{
Sname string
price float64
Qty int
}
Struct B :
type Source_b struct{
Sname2 string
price2 float64
Qty2 int
}
Nested Struct C :
type Data struct{
S_a []Source_a
S_b []Source_b
}
I have declared the Source_a & Source_b type var and derived & assigned the values to it from DB. Sample code for Struct A:
//Post DB query
sks := make([]Source_a, 0)
for rows.Next(){
sk := Source_a{}
err := rows.Scan(&sk.Sname, &sk.Uprice, &sk.Qty)
sks = append(sks, sk)
I am having trouble in binding the values of Struct A & B to Struct C. I am trying something but it is throwing errors, pretty sure this is not the correct way:
td := Data{
S_a: []Source_a{
Source_a{
Sname:sks.Sname,
Uprice:sks.Uprice,
Qty:sks.Qty,
},
},
S_b: []Source_b{
Source_b{
Sname2: sks2.Sname2,
Uprice2: sks2.Uprice2,
Qty2: sks2.Qty2,
},
},
},
Can you please help, I am new to Golang. Let me know if you need clarifications or specifics.
sks and sks2 seem like slices and you are using them as variables. You can do
td := Data{
S_a: sks,
S_b: sks2,
}

How to display all records using struct

I am trying to fetch all data from a table. It returns all data but it is displaying only the last record. I am using GORM and GIN with Golang.
I tried to create a struct and pass that struct to the Find method.
type MpCountry struct{
id uint
Iso string
Name string
Nicename string
Iso3 string
Numcode uint
phonecode uint
}
Code:
countries:= DbModel.MpCountry{}
DbModel.DB.Debug().Find(&countries)
fmt.Println(countries)
fmt.Println("test")
log.Printf("%+v", countries)
return &countries
Output
SELECT * FROM `mp_countries`
[239 rows affected or returned ]
{id:0 Iso:ZW Name:ZIMBABWE Nicename:Zimbabwe Iso3:ZWE Numcode:716 phonecode:0}
You are only passing in a struct, not a slice of structs. It is therefore replacing the values in the struct, until it reaches the last record.
Instead, pass in a pointer to a slice:
countries := &[]DbModel.MpCountry{}
DbModel.DB.Debug().Find(countries)

Go-Gorm | How to use Scan and Preloading

I'm newbie in Go and GORM. I'm having a problem with gorm when I want to join two table and select all field in two table.
My model:
Action:
type Action struct {
ID uint64
Type int
Url string
}
type Reminder struct {
ID uint64 `gorm:"primary_key"`
MerchantID uint64
MerReminderID string
Title string
Description string
ActionID uint64
Action *Action `gorm:"save_associations:false"`
Payload string
StartAt time.Time `gorm:"-"`
EndAt time.Time `gorm:"-"`
}
type UserReminder struct {
UserID uint64
ReminderID uint64
Reminder Reminder
StartAt time.Time
EndAt time.Time
Expired bool
}
My request: I want to get all Reminder of once UserID.
Solution 1:
var reminders []*models.Reminder
err := db.Set("gorm:auto_preload", true).
Raw("SELECT * FROM user_reminders AS ur, reminders AS r WHERE ur.reminder_id = r.id AND ur.user_id = ?", userID).
Preload("Actions").
Scan(&reminders)
=> Promblem: Select all column when join two table but Object Action can't preloading.
Solution 2:
var reminders []*models.Reminder
err := db.Set("gorm:auto_preload", true).
Joins("JOIN user_reminders ON user_reminders.reminder_id = reminders.id").
Where("user_reminders.user_id = ? AND user_reminders.end_at >= ? AND user_reminders.deleted_at IS NULL", userID, time.Now()).
Find(&reminders)
=> Problem: Auto-preload success object Action and select all column in table Reminder. But miss two column Start_At and End_At in table User_Reminder
Please help me this problem. In my case, I want to auto preloading object Action and select all column when join two table Reminder and User_Reminder
Thanks so much.
#Anh Vinh Huynh
Gorm Scan method doesn't support Preloading, so you must use the Find method instead. (your Soloution2)
And remove gorm:"-" tag from StartAt and EndAt of

How to call a function on a custom type

I've seen some similar questions but I can't find one that solves my problem.
I have a custom Money type that aliases int64 with a function that formats the value as a string:
type Money int64
func (m *Money) Format() string {
abs := math.Abs(int64(*m))
dollars := int64(abs) / 100
cents := int64(abs) % 100
sign := ""
if *m < 0 {
sign = "-"
}
return fmt.Sprintf("%s$%d.%0.2d", sign, dollars, cents)
}
I have a HTML template that I pass a data struct. The struct has a list of invoice items on it that each have a Money field, and another Money field that holds the total.
type InvoiceItem {
// ...
Cost money.Money
}
type data struct {
Name string
Items []*model.InvoiceItem
StartDate time.Time
EndDate time.Time
Total money.Money
}
I pass the data to my template and execute it:
t := template.Must(template.New(title).Parse(templateString))
t.Execute(&buf, data)
In my template I range over the invoice items and call the Format function on the Money object. This works:
{{range .Items}}
<tr>
<td>{{.Description}}</td>
<td>{{.Cost.Format}}</td>
</tr>
{{end}}
Later on I attempt to print the total field:
<td><strong>{{ .Total.Format }}</strong></td>
My templates throws an error:
... executing "Invoice Items" at <.Total.Format>: can't evaluate field Format in type money.Money
Why is it that I can call Format on the Money field when I range over the list of invoice items, but I can't call it on the data.Total object? From the error message it seems that the template knows that the type of Total is Money, so what's the problem?
It looks like your data struct is unexported.
Do this:
type Data struct {
}

Golang's GORM not adding associations to "has many" relationship

I just started using GORM and tried to build a "has many relationship". I'm trying to add an association to Previous.Holdings (I think I followed the docs correctly) but when I try to do a select * from previous I don't see anything showing up in the database. Any idea on what I'm missing.
import (
orm "github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/sqlite"
)
type Previous struct {
orm.Model
Holdings []Holding `gorm:"foreignkey:ID"`
}
type Holding struct {
ID uint `gorm:"primary_key"`
Symbol string
PurchaseDate time.Time
SellDate time.Time
}
func main() {
t1, _ := time.Parse("2006-01-02", "2017-06-16")
h := Holding{
Symbol: "abc",
PurchaseDate: t1,
}
db.Model(&Previous{}).Association("Holdings").Append(h)
}
First of all you should create your previous table. You can make that by making migrations. You probably should make that migrations after db connection initialization. e.g.
db.AutoMigrate(&Previous{})
So when u using db.Model(&Previous{}) you not saving any entity and if u wanna make asscociation with Holdings entity you need as first step to Save or Find existing Previous record by doing e.g.
previous := &Previous{}
db.Save(previous)
After that you can append your holding record to Model like you do in your code but changing referenced Previous. So it will look like this
h := Holding{
Symbol: "abc",
PurchaseDate: t1,
}
db.Model(previous).Association("Holdings").Append(h)
I don't know if its for testing but when you modeling entities you can make referenced id whithout specifing foreign key also you are using your Holding ID as ForeignKey so ID of Previous will be your ID of Holding.
For me your model declaration should look like this (PreviousID will be automaticaly signed as foreign key for Previous)
type Previous struct {
orm.Model
Holdings []Holding
}
type Holding struct {
ID uint `gorm:"primary_key"`
PreviousID uint
Symbol string
PurchaseDate time.Time
SellDate time.Time
}

Resources