Gorm 和多对多关系

Gorm and many to many relations

我在理解如何使用 gorm 获取相关信息时遇到问题。这是我第一次主动使用 ORM。

我正在尝试获取特定用户 ID 可以访问的所有设备。使用当前功能,我获得了所有设备,不仅是属于实际用户 ID 的设备,还包括该设备所属的用户列表,这是我目前不需要的信息。

有没有办法使用 gorm 使用 user_devices 加入 table 来获取用户有权访问的设备,或者这是我应该创建自定义查询以实现什么我要?

谢谢。

type User struct {
    ID          uint
    Name        string
    Email       string
    Age         uint8
    Birthday    time.Time
    Password    string
    ActivatedAt time.Time
    OrgID       uint
    Org         Org
    Devices     []Device `gorm:"many2many:user_devices"`
    CreatedAt   time.Time
    UpdatedAt   time.Time
}

type Device struct {
    ID           uint
    Name         string
    Hwaddr       string
    OrgID        uint
    PublicIP     uint
    Org          Org
    Users        []User `gorm:"many2many:user_devices"`
    DeviceType   string
    Identity     string
    LastPolledAt time.Time
    CreatedAt    time.Time
    UpdatedAt    time.Time
}

func (u *Device) FindAllDevicesByUid(db *gorm.DB, user *User) (*[]Device, error) {
    var err error
    devices := []Device{}
    err = db.Debug().Preload("Users", "user_id = ?", user.ID).Find(&devices).Error
    if err != nil {
        return &[]Device{}, err
    }
    return &devices, err
}

结果:

  {
    "ID": 4,
    "Name": "Test 4",
    "Hwaddr": "00:00:00:00:00:04",
    "OrgID": 1,
    "PublicIP": 0,
    "Org": {
      "Id": 0,
      "Name": "",
      "Users": null,
      "CreatedAt": "0001-01-01T00:00:00Z",
      "UpdatedAt": "0001-01-01T00:00:00Z"
    },
    "Users": [
      {
        "ID": 1,
        "Name": "Jan Astrup",
        "Email": "some@email.com",
        "Age": 0,
        "Birthday": "0001-01-01T00:00:00Z",
        "ActivatedAt": "2022-04-24T15:48:40+02:00",
        "OrgID": 1,
        "Org": {
          "Id": 0,
          "Name": "",
          "Users": null,
          "CreatedAt": "0001-01-01T00:00:00Z",
          "UpdatedAt": "0001-01-01T00:00:00Z"
        },
        "Devices": null,
        "CreatedAt": "2022-04-24T15:48:40+02:00",
        "UpdatedAt": "2022-04-24T15:48:40+02:00"
      }
    ],
    "DeviceType": "Router",
    "Identity": "M1923 4",
    "LastPolledAt": "0001-01-01T00:00:00Z",
    "CreatedAt": "2022-04-24T15:17:30+02:00",
    "UpdatedAt": "2022-04-24T15:17:30+02:00"
  }

要仅为特定用户加载设备,您可以使用 Joins 函数连接表 user_devicesdevices

devices := []Device{}
err = db.Debug().Joins("JOIN user_devices ud ON ud.device_id = devices.id").Where("ud.user_id = ?", user.ID).Find(&devices).Error

除此之外,您始终可以加载用户并预加载其设备:

u := User{}
err = db.Debug().Preload("Devices").First(&u, user.ID).Error

然后,你可以使用u.Devices到return用户的设备,但我认为这种方法执行两个查询来获取用户的设备。