我对Go很陌生,我正在做一个Go项目,在那里我使用松鼠进行SQL查询。我有两个表,User和UserLocation,我需要在它们之间执行LEFT JOIN。以下是我的struct:
type User struct {
Slug string `json:"slug" db:"slug"`
Name string `json:"name" db:"name"`
Label null.String `json:"label" db:"label"`
*UserLocation
}
type UserLocation struct {
Id string `json:"uuid" db:"id"`
UserSlug string `json:"user_slug" db:"user_slug"`
Latitude float64 `json:"lat" db:"latitude"`
Longitude float64 `json:"lng" db:"longitude"`
}
UserLocation表中的UserSlug字段是链接到User表的Slug字段的外键字段。
我正在尝试创建一个LEFT JOIN查询,它将返回User数据沿着任何UserLocation数据(如果可用)。下面是我需要的输出格式:
如果在UserLocation表中找到了UserSlug,则返回整个User JSON,并为找到的位置返回一个嵌套对象:
{
slug: "user_slug",
name: "user name",
label: "user label",
location: {
id: "some-uuid",
user_slug: "user_slug",
latitude: 0.123,
longitude: 123.0
}
}
但是,如果在UserLocation中找不到UserSlug,我希望结果根本不包含location键:
{
slug: "user_slug",
name: "user name",
label: "user label"
}
我正试图用这样的东西来实现这一点:
import (
"context"
"database/sql"
"strings"
"time"
"github.com/lib/pq"
sq "github.com/Masterminds/squirrel"
"github.com/pkg/errors"
)
type User struct {
Slug string `json:"slug" db:"slug"`
Name string `json:"name" db:"name"`
Label null.String `json:"label" db:"label"`
*UserLocation
}
type UserLocation struct {
Id string `json:"uuid" db:"id"`
UserSlug string `json:"user_slug" db:"user_slug"`
Latitude float64 `json:"lat" db:"latitude"`
Longitude float64 `json:"lng" db:"longitude"`
}
type UserListResponse struct {
Users []User `json:"users"`
}
func (p *Postgres) ListUsers(
ctx context.Context,
r UserListRequest,
) (UserListResponse, error) {
var response UserListResponse
selectColumns := append(tableUserColumns, tableUserLocationColumns)
qb := sq.Select(selectColumns...).
From(tableUser)
qb = qb.LeftJoin(tableUserLocation + " ON " +
tableColumn(tableUser, columnUserSlug) + " = " + (tableColumn(tableUserLocation, columnUserLocationSlug)))
q, args, err := qb.
ToSql()
if err != nil {
return response, errors.Wrap(err, "select all query q parsing")
}
err = p.db.SelectContext(ctx, &Users, q, args...)
if err != nil {
return response, errors.Wrap(err, "select all query execution")
}
return storyapi.UserListResponse{
Users: Users
}, nil
}
但我一直得到以下错误:
"select all query execution: missing destination name id in *[]User"
如果在UserLocations中没有找到匹配项,我如何以允许我忽略嵌套对象的方式执行LEFT JOIN?
1条答案
按热度按时间r55awzrz1#
我不知道松鼠,所以我会给予你一个答案,当你不想发送空字段时,你可以像这样在结构体中的那个字段的JSON标记中放置omitempty
现在你面临的问题是你的查询不工作,你的用户结构没有字段
id
,这是在数据库中,它试图在你的结构中找到这个字段。所以我的解决方案是如果你想发送你提到的这样的响应
你要做的是不要做左连接,因为你不能将左连接结果Map到与数据库查询结果不同的结构体,所以你必须基于外键在循环中触发单独的查询,如下所示:这不是完美的代码,它只是解释逻辑,它可能有错误(不是语法)
虽然我知道这是非常糟糕的方式,但我有一个解决方案的情况下,你有一个单一的位置为单一用户
只需创建一个新的custome结构体,就像这样,它可以连接查询响应
确保你有唯一的字段,如果你想改变字段名,然后也改变它在db标签,不要忘记把一个别名的名称在sql查询。然后你可以很容易地解析查询响应到你的custome结构,然后将该结构Map到你的原始结构,然后发送响应