Leave a Comment
Golang, PostgreSQL and array_agg
If you have SQL like this:
SELECT c.id, c.description, c.status, array_agg(u.id ORDER BY u.id)::BIGINT[] AS user_ids, array_agg(u.type_id ORDER BY u.id)::BIGINT[] AS user_type_ids, array_agg(u.name ORDER BY u.id)::TEXT[] AS user_names FROM chat_users AS cu INNER JOIN ( SELECT cu.chat_id FROM chat_users AS cu WHERE cu.user_id = $1 ORDER BY chat_id DESC LIMIT $2 OFFSET $3 ) AS cu1 ON cu.chat_id = cu1.chat_id INNER JOIN users AS u ON u.id = cu.user_id INNER JOIN chats AS c ON c.id = cu.chat_id GROUP BY c.id ORDER BY c.id DESC
Then you can query DB like this:
rows, err := master.Query(ctx, query, id, limit, offset)
And scan results like this (you should not omit errors in real code):
var chats []*model.Chat
defer rows.Close()
for rows.Next() {
var (
chat model.Chat
userIDs []sql.NullInt64
userTypes []sql.NullInt64
userExternalIDs []sql.NullString
)
_ = rows.Scan(&chat.ID, &chat.GUID, &chat.Meta, &chat.Status, pq.Array(&userIDs), pq.Array(&userTypes), pq.Array(&userExternalIDs))
if len(userIDs) != len(userTypes) || len(userIDs) != len(userExternalIDs) {
return errors.New("WAAT?!")
}
chat.Users = make([]*model.User, 0, len(userIDs))
for i := range userIDs {
var (
tmp interface{}
ok bool
userID int64
userType int64
userExternalID string
)
tmp, _ = userIDs[i].Value()
userID, _ = tmp.(int64)
tmp, _ = userTypes[i].Value()
userType, _ = tmp.(int64)
tmp, _ = userExternalIDs[i].Value()
userExternalID, _ = tmp.(string)
user := &model.User{
ID: uint64(userID),
TypeID: uint64(userType),
ExternalUserID: userExternalID,
}
chat.Users = append(chat.Users, user)
}
chats = append(chats, &chat)
}
Now you have a list of chats with all it’s users.
You can read more here — https://www.opsdash.com/blog/postgres-arrays-golang.html
LEAVE A COMMENT
Для отправки комментария вам необходимо авторизоваться.