Список с несколькими значениями внешнего ключа sql gorm

#go #foreign-keys #go-gorm

# #Вперед #внешние ключи #go-gorm

Вопрос:

 type Users struct {
    ID           int64      
    Email        string         
    Permissions  string
}
 
 type UserPermissions  struct {
    ID          int64
    Description json.RawMessage
}
 

Пользовательский json должен быть таким:

 {
    "status": 200,
    "data": {
        "id": 1,
        "email": "hello@hello.com",
        "permisions": [{
            "id":"1",
            "description":"Create permission"
         },
         {
            "id":"3",
            "description":"Edit permission"
         }]
    }
}
 

У меня есть следующая строка в разрешениях моего пользователя:

‘;1;3;5;7;’ каждое число — это идентификатор, связанный со структурой / таблицей UserPermissions

Как я могу сопоставить строку с таблицей разрешений пользователя с помощью gorm ?. Я использую mysql

Комментарии:

1. Из вашего кода неясно, есть ли один или много UserTypes для каждого User , потому что у вас есть поле UserType в вашей структуре Users. Какова цель этого поля?

2. решаемая @EzequielMuns. Я уже обновил код. Извините за недопонимание

Ответ №1:

Ответ на ваш вопрос (если вы используете PostgreSQL в качестве своей базы данных).

Если вы хотите запросить разрешения, которые имеет данная пользовательская запись, учитывая ее идентификатор

 perms := []Permission{}
err := db.Joins("JOIN users u ON id::string IN STRING_TO_ARRAY(TRIM(';' FROM u.permissions), ';')").
    Where("u.id = ?", userID).
    Find(amp;perms).
    Error

if err != nil {
    log.Fatal(err) // or something like that
}
 

Как вы можете видеть, мы выполняем простое объединение с функциями, которые очищают и разделяют поле разрешений на отдельные идентификаторы строк. Это неуклюже, хрупко, очень медленно и запутанно, и связано с ошибочным дизайном отношений, с которого вы начали.

РЕДАКТИРОВАТЬ: Неважно, для MySQL эквивалентное решение намного сложнее, поэтому я предлагаю вам вместо этого воспользоваться приведенным ниже советом.

Лучший способ

Если у вас есть контроль над дизайном базы данных, лучшим способом сделать это было бы не хранить массив идентификаторов в виде строки, что никогда не бывает хорошо при проектировании базы данных, а вместо этого использовать внешний ключ на стороне многих отношений hasMany *.

Это будет выглядеть так, как структуры go:

 type User struct {
    ID           int64             `json:"id"`     
    Email        string            `json:"email"`
    Permissions  []UserPermission  `json:"permissions"`
}

type UserPermissions struct {
    ID          int64            `json:"id"`
    UserID      int64            `json:"-"`
    Description json.RawMessage  `json:"description"`
}

// now you can use gorm to query the permissions that are related to a user
user := User{}
err := db.Preload("Permissions").First(amp;user, userID).Error
if err != nil {
    log.Fatal(err)
}
// now you can access user.Permissions[i].Description for example.
// or marshal to json
out, err := json.Marshal(user)
if err != nil {
    log.Fatal(err)
}
fmt.Println(string(out))
 

*: Я предполагаю, что связь между пользователем и разрешением пользователя — один ко многим. Это вполне может быть не так, и отношение «Многие ко многим» на самом деле имеет смысл (у одного пользователя может быть много разрешений, одно разрешение может принадлежать многим пользователям). Если это так, концепции те же, и вы должны иметь возможность изменить это решение, следуя руководству Gorm по отношениям «многие ко многим«.

Комментарии:

1. Привет, @juancer1123, я отредактировал свой ответ, чтобы учесть ваше редактирование.

2. спасибо @EzequielMuns, в этом случае, как вы сказали, я создаю новую таблицу с идентификатором разрешений и идентификатором пользователя, и у меня все еще есть описания разрешений, потому что они общие, тогда мне не нужно писать описание для каждого разрешения. спасибо за совет!