Gorm和多对多关系

huangapple go评论78阅读模式
英文:

Gorm and many to many relations

问题

我有一个问题,不太理解如何使用gorm获取相关信息。这是我第一次积极使用ORM。

我想要获取特定用户ID所能访问的所有设备。使用当前的函数,我获取到的是所有设备,而不仅仅是属于实际用户ID的设备,而且还包括设备所属的用户列表,这些信息在这个阶段我真的不需要。

是否有一种方法可以使用gorm获取用户通过user_devices连接表所能访问的设备,或者我应该创建一个自定义查询来实现我想要的功能?

谢谢。

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"
}
英文:

I have an issue understanding how to fetch related information using gorm. This is the first time ever I'm using an ORM actively.

I'm trying to get all devices that a specific user id has access to. With the current function I get all devices, not only the device belonging to the actual user id, and it also includes the list of users that the device belongs to, which is information i really don't need at this point.

Is there a way to Get the devices that the user has access to using the user_devices join table using gorm, or is this something i should create a custom query in order to achieve what I want?

Thank you.

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
}

Result:

  {
    "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"
  }

答案1

得分: 1

加载特定用户的设备,可以使用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来返回用户的设备,但我认为这种方法执行了两个查询来获取用户的设备。

英文:

To load just the devices for a specific user, you can use the Joins function to join tables user_devices and devices.

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

Apart from this, you can always load the user and preload its devices:

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

Then, you can use u.Devices to return the user's devices, but I think this approach executes two queries to get the user's devices.

huangapple
  • 本文由 发表于 2022年4月25日 18:31:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/71998119.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定