根据外键关系获取基于 GORM 模型的行(使用 Golang)

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

Get GORM model row based on foreign key relationship (golang)

问题

我正在使用Golang(GORM)+ Postgres。我正在尝试建模一个商业情景,其中卖家向买家销售商品,每个交易都创建一个订单。

我有一个Order Gorm模型,以及一个Buyer和一个Seller Gorm模型。买家和卖家已经在数据库中创建了行。

一个买家有多个订单。

一个卖家有多个订单。

为了映射这个关系,我认为我只需要创建相应的Buyer/Seller结构体(标准的Gorm模型),然后创建一个Order结构体,如下所示:

type Order struct {
	ID        int64       `json:"ID" gorm:"primary_key;auto_increment:true"`
	Buyer     *Buyer      `json:"Buyer"`
	Seller    *Seller     `json:"Seller"`
    // ... 其他数据 ...
}

我假设上述代码会自动创建关系,但我不完全确定。我可以使用以下函数创建一个Order,这个函数返回正常:

func CreateOrder(buyer *entity.Buyer, seller *entity.Seller) (*entity.Order, error) {
	order := &entity.Order{
		User:   buyer,
		Sitter: seller,
		// ... 其他数据 ...
	}
	db.Table("orders").Create(order)
	return order
}

如果我进入Postgres CLI,TABLE orders;不会显示buyer或seller列。我期望看到它们的ID列。所以这就是为什么我不确定这是否有效。这本身可能就是一个问题。

无论如何,我真正想做的是能够检查买家/卖家是否存在任何订单。但我真的看不到使用gorm查询的任何方法来实现这一点。我想在SQL中应该是这样的:

func FindOrder(buyer *entity.Buyer, seller *entity.Seller) {
     db.Raw(`SELECT order FROM orders WHERE buyer = ? AND seller = ?`, buyer, seller)
     // 或者是这样的???
     db.Table("orders").Where("buyer = ? AND seller = ?", buyer, seller).First(&order)
}

但我不知道是否有任何Gorm辅助函数可以实现这一点。我还希望这种方法是高效的,因为买家和卖家都有它们的ID主键。

如何根据买家/卖家找到一个Order,就像上面的例子一样?

作为一种替代方案,我考虑添加(买家ID + 卖家ID)来创建一个自定义的订单ID作为primary_key。但我觉得这样做有点繁琐,因为我觉得关系的整个目的就是为了避免这样做。

英文:

I am using Golang (GORM) + Postgres. I am trying to model a business situation where a seller sells things to buyers, each creating an order transaction.

I have an Order Gorm model, as well as a Buyer and a Seller Gorm model. The Buyer and the Seller are already rows created in the database.

One buyer HasMany orders.

One seller HasMany orders.

To map out this relation, I believe I just create the respective Buyer/Seller struct (standard Gorm models), and then make an Order struct like so:

type Order struct {
	ID        int64       `json:"ID"gorm:"primary_key;auto_increment:true"`
	Buyer     *Buyer      `json:"Buyer"`
	Seller    *Seller     `json:"Seller"`
    // ... other data ...
}

I'm assuming the above automatically creates the relationship, but I am not entirely sure. I can create an Order with this function, and this returns fine:

func CreateOrder(buyer *entity.Buyer, seller *entity.Seller) (*entity.Order, error) {
	order := &entity.Order{
		User:   buyer,
		Sitter: seller,
		// ... other data ...
	}
	db.Table("orders").Create(order)
	return order
}

If I go to Postgres CLI, the TABLE orders; does not show the columns buyer or seller. I would expect a column of their IDs. So this is why I am unsure this is working. This could definitely be a problem in itself.

Anyways, what I really want to do is be able to check if any orders currently exist for a Buyer / Seller. But I don't really see anyway to do that with gorm queries. I would imagine in SQL it would be something like:

func FindOrder(buyer *entity.Buyer, seller *entity.Seller) {
     db.Raw(`GET order FROM orders WHERE buyer = ?, seller = ?`, buyer, seller)
     // OR this ???
     db.Table("orders").First(buyer, buyer).First(seller, seller)
}

But I don't know of any Gorm helper function that actually does this. I also want this to be efficient because buyer and seller each have their ID primary keys.

How can I find an Order based on the Buyer / Seller like in the example above?

As an alternative, I am thinking of adding (buyer ID + seller ID) to make a custom order ID primary_key. This seems hacky though, as I feel like the whole point of relations is so I don't have to do something like this.

答案1

得分: 1

如果你需要在订单表中查看卖家ID和买家ID,请在你的订单结构体中包含这两个字段,并使用foreignKey标签填充这些字段(默认情况下,它们会填充为关联表记录的主键ID,你可以使用references标签来更改这一点,详情请参考这里)。

type Order struct {
    ID       int64  `json:"id" gorm:"primaryKey;autoIncrement:true"`
    BuyerID  int64  `json:"buyer_id" gorm:"index"`
    SellerID int64  `json:"seller_id" gorm:"index"`
    Buyer    *Buyer `json:"buyer" gorm:"foreignKey:BuyerID"`
    Seller   *Seller `json:"seller" gorm:"foreignKey:SellerID"`
}

type Buyer struct {
    ID   int64  `json:"id" gorm:"primaryKey;autoIncrement:true"`
    Name string `json:"name"`
}

type Seller struct {
    ID   int64  `json:"id" gorm:"primaryKey;autoIncrement:true"`
    Name string `json:"name"`
}

至于根据买家和卖家查找订单的函数,你可以使用类似下面的代码:

func findOrders(db *gorm.DB, buyerID int, sellerID int) []Order {
    orders := make([]Order, 0)
    db.Where("buyer_id=? AND seller_id=?", buyerID, sellerID).Find(&Order{}).Scan(&orders)
    return orders
}

相反,如果你需要查找给定买家或卖家的订单,可以使用以下代码:

func findOrder(db *gorm.DB, buyerID int, sellerID int) []Order {
    orders := make([]Order, 0)
    db.Where("buyer_id=? OR seller_id=?", buyerID, sellerID).Find(&Order{}).Distinct().Scan(&orders)
    return orders
}

index标签用于覆盖orders表的索引要求。

根据外键关系获取基于 GORM 模型的行(使用 Golang)

英文:

If you need to see the seller id and the buyer id in the orders table, include two fields for that in your orders struct, also you can use the foreignKey tag to populate those fields (by default they are populated with the primary id of the associated table record, you can use references tag as mentioned here to change that).

type Order struct {
	ID int64 `json:"id" gorm:"primaryKey;autoIncrement:true"`
	BuyerID int64 `json:"buyer_id" gorm:"index"`
	SellerID int64 `json:"seller_id" gorm:"index"`
	Buyer *Buyer `json:"buyer" gorm:"foreignKey:BuyerID"`
	Seller *Seller	`json:"seller" gorm:"foreignKey:SellerID"`
}

type Buyer struct {
	ID int64	`json:"id" gorm:"primaryKey;autoIncrement:true"`
	Name string `json:"name"`
}

type Seller struct {
	ID int64	`json:"id" gorm:"primaryKey;autoIncrement:true"`
	Name string  `json:"name"`
}

As for the function to find orders given the buyer AND the seller you can use something like,

func findOrders(db *gorm.DB, buyerID int,sellerID int)[]Order{
	orders := make([]Order,0)
	db.Where("buyer_id=? AND seller_id=?",buyerID,sellerID).Find(&Order{}).Scan(&orders)
	return orders
}

in contrast if you need to find orders for a given buyer OR the seller,

func findOrder(db *gorm.DB, buyerID int,sellerID int)[]Order{
	orders := make([]Order,0)
	db.Where("buyer_id=? OR seller_id=?",buyerID,sellerID).Find(&Order{}).Distinct().Scan(&orders)
	return orders
}

The index tag covers the indexing requirement for orders table.

根据外键关系获取基于 GORM 模型的行(使用 Golang)

答案2

得分: -2

使用简单的原始查询构建器处理大型查询
https://perfilovstanislav.github.io/go-raw-postgresql-builder/#simple-example

英文:

Use simple raw query builder for large queries
https://perfilovstanislav.github.io/go-raw-postgresql-builder/#simple-example

huangapple
  • 本文由 发表于 2021年7月27日 03:38:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/68535536.html
匿名

发表评论

匿名网友

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

确定