Получить вложенный объект в структуре в gorm

У меня есть две структуры:

type GoogleAccount struct {
     Id     uint64
     Token  string
}

Он представляет мой собственный тип объекта PostgreSQL (я создал сам):

CREATE TYPE GOOGLE_ACCOUNT AS
(
  id    NUMERIC,
  token TEXT
);

И следующая структура таблицы в БД:

type Client struct {
     IdClient       uint64          `gorm:"primary_key"`
     Name           string
     PhotoUrl       string
     ApprovalNumber uint16
     Phone          string
     Password       string
     HoursOfNotice  int8
     Google         GoogleAccount
}

И мой пользовательский объект вложен в типе клиента и назван как google, Я попытался прочитать данные следующим образом:

var users model.Client
db.First(&users)

Но, к сожалению, я не могу прочитать поле google (иметь значение по умолчанию). Я не хочу создавать отдельную таблицу с google_account, или делать эту структуру как отдельные поля в клиентской таблице или упаковывать ее как json (создал отдельную сущность, потому что эта структура используется не только в этой таблице, и я ищу новые способы, которые получить тот же результат, но более изящно). Задача не состоит в том, чтобы упростить представление данных в таблице. Мне нужно сделать правильное отображение объекта от postgres до сущности.

Прямо сейчас я нашел одно решение - внедрить Scanner в GoogleAccount. Но значение в методе ввода равно []uint8. Как я могу предположить, []uint8 может приводить к строке, и после этого я могу проанализировать эту строку. Эта строка (которая хранится в БД) выглядит (x,x) где х - это значение. Это правильный способ, чтобы разобрать строку и установить значение для объекта? Или есть способ получить этот результат с помощью ORM?

Возможен ли способ чтения этих данных как объекта вложенной структуры?

2 ответа

Решение

Прямо сейчас я нашел одно решение - внедрить Scanner для GoogleAccount, На входе Scan метод, который я получил []uint8, что я приведу к строке и разобрать в конце. Эта строка (которая хранится в БД) выглядит (x,x) - где x - это ценность. Конечно, это не правильный способ достижения моей цели. Но я не мог найти другое решение.

Я настоятельно рекомендую использовать классическое связывание по отношениям или просто хранить эти поля в таблице как простейшее значение (а не как объект).

Но если вы хотите поэкспериментировать с вложенным объектом в таблице, вы можете взглянуть на мою реализацию, может быть, она будет вам полезна: https://github.com/kirikzyusko1996/go-cleaning-api/blob/master/src/app/model/client.go

Похоже, вы захотите сделать две вещи с тем, что у вас есть: (1) обновить модель, чтобы у вас была правильная привязка отношений, и (2) использовать .Preload() метод, если вы пытаетесь заставить его связать данные при чтении.

Модельные Изменения

Gorm автоматически определяет отношения на основе имени атрибутов в вашей структуре и имени ссылочной структуры. Проблема в том, что Google атрибут типа GoogleAccount не ассоциирует, потому что Горм ищет type Google struct,

Вам также не хватает внешнего ключа на GoogleAccount, Как ORM узнает, какие GoogleAccount ассоциировать с которым Client? Вы должны добавить ClientId на ваш GoogleAccount определение структуры.

Кроме того, я бы изменил первичные ключи, которые вы используете для ввода uint так как это то, что Gorm по умолчанию (если у вас нет веских причин не использовать его)

Если бы я был тобой, я бы изменил мои определения структуры следующим образом:

type Client struct {
     IdClient       uint            `gorm:"primary_key"`
     Name           string
     PhotoUrl       string
     ApprovalNumber uint16
     Phone          string
     Password       string
     HoursOfNotice  int8
     GoogleAccount  GoogleAccount    // Change this to `GoogleAccount`, the same name of your struct
}

type GoogleAccount struct {
     Id             uint
     ClientId       uint             // Foreign key
     Token          string
}

Для получения дополнительной информации об этом, посмотрите на документацию ассоциаций здесь: http://gorm.io/associations.html

Предварительная загрузка ассоциаций

Теперь, когда вы правильно их связали, вы можете .Preload() получить вложенный объект, который вы хотите:

db.Preload("GoogleAccount").First(&user)

С помощью .Preload() будет заселять user.GoogleAccount атрибут с правильно связанным GoogleAccount на основе ClientId,

Для получения дополнительной информации об этом обратитесь к документации по предварительной загрузке: http://gorm.io/crud.html

Другие вопросы по тегам