I'm trying to Preload data from a One to Many relationship, yet I always get an "ApiKeys: unsupported relations for schema Client" error. (The reason structs are pointers is because I'm using gqlgen and that's the default configuration)
type Client struct {
// Client ID
ID int `json:"id"`
UserName string `json:"userName"`
// Client login hashed password
Password string `json:"password"`
// ApiKeys
APIKeys []*APIKey `json:"apiKeys"`
}
type APIKey struct {
// ApiKey Index
ID int `json:"id"`
// ApiKey Value
Key string `json:"key"`
// ApiKey Client Relation
ClientID int `json:"clientID"`
// ApiKey Client Info
Client *Client `json:"client"`
}
And this is the function that calls the Preload of ApiKeys.
func (r *queryResolver) ClientInfoResolver(username string, password string) (*model.Client, error) {
var clients []*model.Client
var client *model.Client
query := r.Resolver.DB
query = query.Where("user_name = ? AND password = ?", username, password).Preload("ApiKeys").Find(&clients)
if query.Error != nil {
return client, query.Error
}
return clients[0], nil
}
I understand by gorm's documentation that the foreign key for the relation is ClientID, despite not being explicit (doesn't work by specifying it either) am I understanding something wrong here?
You list APIKeys
as the struct field name but try and use ApiKeys
as the FK.
.Preload("ApiKeys")
// Should be
.Preload("APIKeys")
Or, if you want to use ApiKeys
as the foreign key, use a Gorm struct tag to do this.
package main
import (
"fmt"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
type Client struct {
// ApiKey Index
ID int `json:"id"`
UserName string `json:"userName"`
// Client login hashed password
Password string `json:"password"`
// ApiKeys
APIKeys []*APIKey `json:"apiKeys"`
}
type APIKey struct {
// ApiKey Index
ID int `json:"id"`
// ApiKey Value
Key string `json:"key"`
// ApiKey Client Relation
ClientID int `json:"clientID"`
// ApiKey Client Info
Client *Client `json:"client"`
}
func main() {
db, err := gorm.Open(sqlite.Open("many2many.db"), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
// Migrate the schema
err = db.AutoMigrate(&APIKey{}, &Client{})
if err != nil {
fmt.Print(err)
}
clientOne := Client{
UserName: "Client One",
}
db.Create(&clientOne)
apiKeyOne := APIKey{
Key:"one",
Client: &clientOne,
}
apiKeyTwo := APIKey{
Key:"two",
Client: &clientOne,
}
db.Create(&apiKeyOne)
db.Create(&apiKeyTwo)
// Fetch from DB
fetchedClient := Client{}
db.Debug().Preload("APIKeys").Find(&fetchedClient, clientOne.ID)
fmt.Println(fetchedClient)
db.Delete(&clientOne)
db.Delete(&apiKeyOne)
db.Delete(&apiKeyTwo)
}