亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

有效地將一對多多對多數據庫映射到 Golang 中的結構

有效地將一對多多對多數據庫映射到 Golang 中的結構

Go
慕工程0101907 2023-06-05 17:44:05
問題在 Golang 中處理一對多或多對多 SQL 關系時,將行映射到結構的最佳(有效、推薦、“Go-like”)方式是什么?采用下面的示例設置,我嘗試詳細說明一些方法以及每種方法的優缺點,但想知道社區推薦的內容。要求與 PostgreSQL 一起工作(可以是通用的但不包括 MySQL/Oracle 特定功能)效率 - 沒有暴力強制每個組合沒有 ORM - 理想情況下只使用database/sql和jmoiron/sqlx例子為了清楚起見,我刪除了錯誤處理楷模type Tag struct {  ID int  Name string}type Item struct {  ID int  Tags []Tag}數據庫CREATE TABLE item (  id                      INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY);CREATE TABLE tag (  id                      INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,  name                    VARCHAR(160),  item_id                 INT REFERENCES item(id));方法 1 - 選擇所有項目,然后為每個項目選擇標簽var items []Itemsqlxdb.Select(&items, "SELECT * FROM item")for i, item := range items {  var tags []Tag  sqlxdb.Select(&tags, "SELECT * FROM tag WHERE item_id = $1", item.ID)  items[i].Tags = tags}優點簡單的容易明白缺點數據庫查詢數量與項目數量成比例增加時效率低下方法 2 - 手動構建 SQL 連接并遍歷行var itemTags = make(map[int][]Tag)var items = []Item{}rows, _ := sqlxdb.Queryx("SELECT i.id, t.id, t.name FROM item AS i JOIN tag AS t ON t.item_id = i.id")for rows.Next() {  var (    itemID  int    tagID   int    tagName string  )  rows.Scan(&itemID, &tagID, &tagName)  if tags, ok := itemTags[itemID]; ok {    itemTags[itemID] = append(tags, Tag{ID: tagID, Name: tagName,})  } else {    itemTags[itemID] = []Tag{Tag{ID: tagID, Name: tagName,}}  }}for itemID, tags := range itemTags {  items = append(Item{    ID: itemID,    Tags: tags,  })}優點一個單一的數據庫調用和游標,可以在不消耗太多內存的情況下循環缺點在結構上使用多個連接和許多屬性進行復雜且更難開發不太高效;更多的內存使用和處理時間與更多的網絡調用
查看完整描述

2 回答

?
慕桂英3389331

TA貢獻2036條經驗 獲得超8個贊

我可以建議我以前使用過的另一種方法。


在這種情況下,您在查詢中生成標簽的 json 并將其返回。


優點:您有 1 次調用 db,它聚合數據,您所要做的就是將 json 解析為一個數組。


缺點:有點難看。請隨意抨擊我。


type jointItem struct {

  Item 

  ParsedTags string

  Tags []Tag `gorm:"-"`

}


var jointItems []*jointItem

db.Raw(`SELECT 

  items.*, 

  (SELECT CONCAT(

            '[', 

             GROUP_CONCAT(

                  JSON_OBJECT('id', id,

                             'name', name 

                  )

             ), 

            ']'

         )) as parsed_tags 

   FROM items`).Scan(&jointItems)


for _, o := range jointItems {

var tempTags []Tag

   if err := json.Unmarshall(o.ParsedTags, &tempTags) ; err != nil {

      // do something

   }

  o.Tags = tempTags

}


編輯:代碼可能表現得很奇怪,所以我發現在移動時最好使用臨時標簽數組而不是使用相同的結構。


查看完整回答
反對 回復 2023-06-05
?
慕沐林林

TA貢獻2016條經驗 獲得超9個贊

您可以使用來自https://github.com/jackskj/carta的 carta.Map() 它會自動跟蹤有很多關系。



查看完整回答
反對 回復 2023-06-05
?
江戶川亂折騰

TA貢獻1851條經驗 獲得超5個贊

postgres 中的 sql:


create schema temp;

set search_path = temp;

create table item

(

  id INT generated by default as identity primary key

);


create table tag

(

  id      INT generated by default as identity primary key,

  name    VARCHAR(160),

  item_id INT references item (id)

);


create view item_tags as

select id,

  (

          select

            array_to_json(array_agg(row_to_json(taglist.*))) as array_to_json

          from (

                select tag.name, tag.id

                 from tag

                         where item_id = item.id

               ) taglist ) as tags

from item ;



-- golang query this maybe 

select  row_to_json(row)

from (

    select * from item_tags

) row;


然后golang查詢這個sql:


select  row_to_json(row)

from (

    select * from item_tags

) row;

并解組去結構:

親:

  1. postgres 管理數據的關系。使用 sql 函數添加/更新數據。

  2. golang 管理業務模型和邏輯。

這很簡單。


查看完整回答
反對 回復 2023-06-05
  • 2 回答
  • 0 關注
  • 236 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號