在GORM中组合2个或更多模型来生成 struct 结果的最佳方式是什么?

给定这些示例模型:

type Book struct {
 gorm.Model
 Title string
 Description string
 AuthorID uint
}
type Author struct {
 gorm.Model
 FirstName string
 LastName string
 Books []Book
}

我想创建一个按标题查找图书的查询

db.Where("title=?", "foo").Find(&books)

到目前为止没有问题,但我还想在结果中包括Author.FirstName和Author.LastName.这不适用于我try 过的任何方法,因为Book Struct不包括这些字段.期望的结果应该包括来自匹配图书的所有字段,以及来自与该图书相关的作者的所有字段.

try 使用Select()和Join()函数来指定所有所需的字段,这会生成正确的SQL语句,但生成的Book struct 仍然不包含任何Author字段.

推荐答案

I was able to accomplish your request in this way.
First, I added Author Author field to the Book struct. In this way, you can save the information of the author together with his books.
In the query, you've to use Preload("Auhtor") to let GORM load also the information from the authors table. This practice is called eager-loading. Below, you can find my working solution:

package main

import (
    "fmt"

    "gorm.io/driver/postgres"
    "gorm.io/gorm"
)

type Book struct {
    gorm.Model
    Title       string
    Description string
    AuthorID    uint
    Author      Author
}

type Author struct {
    gorm.Model
    FirstName string
    LastName  string
    Books     []Book
}

func main() {
    dsn := "host=localhost user=postgres password=postgres dbname=postgres port=5432 sslmode=disable"
    db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
    if err != nil {
        panic(err)
    }

    db.AutoMigrate(&Book{})
    db.AutoMigrate(&Author{})

    book1 := &Book{Title: "Go", Description: "Intro to Golang", AuthorID: 1}
    book2 := &Book{Title: "GORM", Description: "Intro to GORM", AuthorID: 1}

    author := &Author{FirstName: "John", LastName: "Doe", Books: []Book{*book1, *book2}}

    db.Create(author)

    var books []Book
    db.Preload("Author").Where("title=?", "Go").Find(&books)
    for _, v := range books {
        fmt.Println("book 1:")
        fmt.Printf("title: %q\n\n", v.Title)

        fmt.Printf("author details:\n")
        fmt.Printf("first name: %q\n", v.Author.FirstName)
        fmt.Printf("last name: %q\n", v.Author.LastName)
    }
}

希望这能帮助你理解.

Go相关问答推荐

我不能让GIO画一个按钮

难以为多个平台添加Go Bazel构建选项

golang.org/x/oauth2 oauth2.Config.Endpoint.TokenURL mock:缺少access_token

如何防止程序B存档/删除围棋中程序A当前打开的文件?

JetBrains Goland,禁用突出显示测试文件

日志(log)文件不在 golang 的日志(log)目录中

在golang中以JSON格式获取xwwwformurlencoded请求的嵌套键值对

gopacket:IP-in-IP 数据包上的解码层

Go 中如何调用测试函数?

Golang代码判断第一个词是否可以从第二个词形成

在 .go 文件中运行一个函数和在 Go 模板中调用它有什么区别?

regex.ReplaceAll 但如果替换则添加相同数量的字符

assert: mock: I don't know what to return because the method call was unexpected 在 Go 中编写单元测试时出错

访问传递给可变参数函数的通用 struct 的特定字段

grpc-gateway:重定向与定义不匹配(原始文件)

如何在自定义验证函数中获取 struct 名称

Golang invopop jsonschema 使用 if/then/else

使用 `didip/tollbooth` 限制每小时最大请求数

Go 并发、goroutine 同步和关闭通道

关系不存在 GORM