我正在将复杂的PostgreSQL选择结果解析为golang结构。 我能够将一个文本数组解析为一个字段,将复合类型的行解析为另一个字段,但是我还需要使第二个字段为行数组,而我无法使用go-解析该array(row())结构pg驱动程序。
这里正在工作的SQL返回单行作为字段variants
select p.*,
array(select url from image i where p.prod_id = i.prod_id) as images,
(select v from prod_variation v where v.prod_id = p.prod_id limit 1) as variants
from product p limit 1;
这是需要解析的SQL请求
select p.*,
array(select url from image i where p.prod_id = i.prod_id) as images,
array(select v from prod_variation v where v.prod_id = p.prod_id) as variants
from product p limit 1;
通知字段变体已添加array()
构造函数,并从子选择中删除了limit 1
。
在golang代码中,产品结构具有此字段定义
Images []string `sql:",array"`
Variants ProdVariant `sql:"composite:prod_variation"`
我正在寻找将第二行重写为类似内容的功能
Variants []ProdVariant `sql:",array,composite:prod_variation"`
但是通过这种方式(并通过更改SQL请求),我得到了go-pg错误:panic: got slice, wanted struct
完整代码如下。
用于创建和填充数据库的SQL
CREATE TABLE product (
prod_id integer primary key,
name text,
price real
);
CREATE TABLE prod_variation (
aid integer primary key,
prod_id integer references product(prod_id),
stock_count integer,
color text
);
CREATE TABLE image (
prod_id integer references product(prod_id),
url text,
primary key (url,prod_id)
);
CREATE INDEX on image (prod_id);
CREATE INDEX on prod_variation (prod_id);
INSERT INTO product(prod_id, name, price) VALUES (1, 'Prod 1', 10.0);
INSERT INTO image(prod_id, url) VALUES (1, 'http://url.com/p1-1.jpg');
INSERT INTO image(prod_id, url) VALUES (1, 'http://url.com/p1-2.jpg');
INSERT INTO prod_variation(aid,prod_id, stock_count, color) VALUES (11, 1, 5, 'red');
INSERT INTO prod_variation(aid,prod_id, stock_count, color) VALUES (12, 1, 7, 'blue');
INSERT INTO product(prod_id,name, price) VALUES (2, 'Prod 2', 20.0);
INSERT INTO image(prod_id, url) VALUES (2, 'http://url.com/p2-1.jpg');
INSERT INTO image(prod_id, url) VALUES (2, 'http://url.com/p2-2.jpg');
INSERT INTO prod_variation(aid,prod_id, stock_count, color) VALUES (21, 2, 10, 'black');
INSERT INTO prod_variation(aid,prod_id, stock_count, color) VALUES (22, 2, 15, 'white');
这是从PostgreSQL服务器中选择数据的golang代码
package main
import (
"log"
"github.com/go-pg/pg"
_ "github.com/go-pg/pg/orm"
"github.com/kylelemons/godebug/pretty"
)
type Product struct {
tableName struct{} `pg:",discard_unknown_columns"sql:"product"`
ProdId uint64 `sql:",pk"`
Name string
Price float32 `sql:",notnull"`
Images []string `sql:",array"`
Variants ProdVariant `sql:"composite:prod_variation"`
}
type ProdVariant struct {
tableName struct{} `pg:",discard_unknown_columns"sql:"prod_variation"`
AID string `sql:",pk"`
ProdId string `pg:"fk:prod"`
StockCount int `sql:",notnull"`
Color string
}
type ProductImage struct {
tableName struct{} `pg:",discard_unknown_columns"sql:"image"`
ProdId uint64 `pg:"fk:prod"`
URL string
}
func selectProducts(tx *pg.Tx) error {
queryFormat := `select p.*,
array(select url from image i where p.prod_id = i.prod_id) as images,
(select v from prod_variation v where v.prod_id = p.prod_id limit 1) as variants
from product p limit 1;`
Res := []Product{}
if _, err := tx.Query(&Res, queryFormat); err != nil {
return err
}
log.Printf("Select result: %s", pretty.Sprint(&Res))
return nil
}
func main() {
opt := pg.Options{Addr: "127.0.0.1:5432", User: "tester", Password: "test12345", Database: "test"}
conn := pg.Connect(&opt)
if err := conn.RunInTransaction(selectProducts); err != nil {
log.Fatalf("Request failed [product]: %s", err)
}
}
此go代码将结果输出到该输出中
2019/01/25 03:15:13 Select result: [{ProdId: 1,
Name: "Prod 1",
Price: 10,
Images: ["http://url.com/p1-1.jpg",
"http://url.com/p1-2.jpg"],
Variants: {AID: "11",
ProdId: "1",
StockCount: 5,
Color: "red"}}]