英文:
go-pg how to select also entity from related table?
问题
类型 Book 结构体 {
tableName struct{} `pg:"book" json:"-"`
Id int `pg:"id,pk" json:"id"`
Author int `pg:"author_id,notnull" json:"-"`
Author *Author `pg:"fk:author_id" json:"author,omitempty"`
}
我想在一次查询中选择书籍和作者。
如果我尝试这样做:
var r []model.Book
_, err := dao.FusedDb.Query(&r, `SELECT * FROM book b INNER JOIN author a on a.id = b.author_id`)
我会得到一个错误
pg: can't find column=name in model=Book (try discard_unknown_columns)
<details>
<summary>英文:</summary>
type Book struct {
tableName struct{} pg:"book" json:"-"
Id int pg:"id,pk" json:"id"
Author int pg:"author_id,notnull" json:"-"
Author *Author pg:"fk:author_id" json:"author,omitempty"
}
I want select book and author in one query.
If I try this:
var r []model.Book
_, err := dao.FusedDb.Query(&r, SELECT * FROM book b INNER JOIN author a on a.id = b.author_id
)
I get an error
> pg: can't find column=name in model=Book (try discard_unknown_columns)
</details>
# 答案1
**得分**: 1
我写了一段代码,每次处理这种情况时都会用到。首先,让我展示代码,然后我会对相关部分进行评论:
```go
package main
import (
"database/sql"
"fmt"
_ "github.com/lib/pq"
)
type Book struct {
gorm.Model
Title string
Description string
AuthorID uint
Author Author
}
type Author struct {
gorm.Model
FirstName string
LastName string
Books []Book
}
type Result struct {
BookId int
AuthorId int
Title string
FirstName string
LastName string
}
func main() {
conn, err := sql.Open("postgres", "host=localhost user=postgres password=postgres dbname=postgres port=5432 sslmode=disable")
if err != nil {
panic(err)
}
defer conn.Close()
// 查询
var result []Result
rows, err := conn.Query("select b.id, a.id, b.title, a.first_name, a.last_name from authors a inner join books b on a.id = b.author_id")
if err != nil {
panic(err)
}
defer rows.Close()
for rows.Next() {
var record Result
if err := rows.Scan(&record.BookId, &record.AuthorId, &record.Title, &record.FirstName, &record.LastName); err != nil {
panic(err)
}
result = append(result, record)
}
if err := rows.Err(); err != nil {
panic(err)
}
fmt.Printf("%v", result)
}
结构体定义
Book
和 Author
结构体表示我数据库中定义的表。Result
用于保存通过下面指定的查询获取的记录。
查询
查询非常简单。我们只在 main
函数开始时使用 SQL 客户端的 Query
方法。然后,我们需要延迟调用 rows
变量的 Close
方法进行清理。
扫描
for
循环确保我们扫描了 Query
方法检索到的所有行。为了判断是否还有其他行需要获取,我们使用 Next
方法,它返回一个布尔值,指示是否还有其他行需要扫描。
在 for
循环的主体中,我们声明一个循环作用域变量来保存当前记录。通过 Scan
方法,我们将能够将每个列分配给结构体的相应字段。
最后,我们需要通过在 rows
变量上调用 Err
方法来检查是否有任何错误,并进行处理。
如果这解答了你的问题,请告诉我,谢谢!
英文:
I wrote down a piece of code that I always use when I've to deal with this scenario. First, let me show the code and then I'll comment on the relevant parts:
package main
import (
"database/sql"
"fmt"
_ "github.com/lib/pq"
)
type Book struct {
gorm.Model
Title string
Description string
AuthorID uint
Author Author
}
type Author struct {
gorm.Model
FirstName string
LastName string
Books []Book
}
type Result struct {
BookId int
AuthorId int
Title string
FirstName string
LastName string
}
func main() {
conn, err := sql.Open("postgres", "host=localhost user=postgres password=postgres dbname=postgres port=5432 sslmode=disable")
if err != nil {
panic(err)
}
defer conn.Close()
// query
var result []Result
rows, err := conn.Query("select b.id, a.id, b.title, a.first_name, a.last_name from authors a inner join books b on a.id = b.author_id")
if err != nil {
panic(err)
}
defer rows.Close()
for rows.Next() {
var record Result
if err := rows.Scan(&record.BookId, &record.AuthorId, &record.Title, &record.FirstName, &record.LastName); err != nil {
panic(err)
}
result = append(result, record)
}
if err := rows.Err(); err != nil {
panic(err)
}
fmt.Printf("%v", result)
}
Structs definition
The Book
and Author
structs represent the tables defined in my database. Result
is used to hold the fetched records through the query specified below.
The query
The query is pretty straightforward. We only used the method Query
on the SQL client opened at the beginning of the main
function. Then, we've to defer a call to the method Close
on the rows
variable to clean up.
Scanning
The for
makes sure that we scan all of the rows retrieved with the Query
method. To understand if there are other rows to fetch we use the method Next
that returns a bool value indicating whether or not there are other rows to scan.
In the body of the for
we declare a loop-scoped variable to hold the current record. Thanks to the Scan
method we'll be able to assign each column to the relative field of the struct.
Lastly, we've to check for any error by invoking the method Err
on the rows
variable and handle it.
Let me know if this clarifies your question, thanks!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论