【问题标题】:Query JSONB columns with GORM for operator in使用 GORM for operator in 查询 JSONB 列
【发布时间】:2021-09-06 21:27:15
【问题描述】:

我有一张像下面这样的表格

INSERT INTO switches VALUES ('33', 60, jsonb_build_object('IDs',jsonb_build_array('11', '2'),'ID', '33', 'Name', 'switch1'));

我有一个结构/模型

type switches struct {
    ID         string `gorm:"primary_key; unique; json:id"`
    Generation uint32 `gorm:"type:integer; column:generation;" json:"generation" `
    // Additional gorm type jsonb set, if not present causes field to be bytea
    SwitchAttrs []byte `sql:"type:jsonb; not null; column:Switch_attrs;" gorm:"type:jsonb; json:switchAttrs"`
}

我可以在 postgres 中查询

SELECT * FROM switches WHERE switch_attrs->'IDs' ? '2' 
id | generation  |       data
----+-------+------------------
33 | 60 | {"IDs": ["33","2"] }

如何针对特定键在 jsonB 列上构造查询?我找不到任何使用模型对象进行查询的文档,其中解释了如何使用“in”运算符。我了解它可能与原始查询有关,但想看看如何使用模型对象来完成。我正在尝试进行如下查询,但失败了:(

db = db.Where("Switch_attrs->'IDs' ?", "2").Find(&switches) 

db = db.Where("Switch_attrs->'IDs' ?",  []string{"2"}).Find(&switches) 

db = db.Where("Switch_attrs->'IDs' IN ?", []string{"2"}).Find(&switches) 

db = db.Where("Switch_attrs->>'IDs' ?",  "2").Find(&switches) . Note that i am querying as switch_attrs->>'IDs' . i expect the o/p as text and hence passing the value as "2".

对于最后一个查询,我不断收到错误

“严重性”:“错误”,“代码”:“42601”,“消息”:“语法错误 或“$1”附近,

【问题讨论】:

    标签: jsonb go-gorm


    【解决方案1】:

    重新定义你的模型如下

    type switches struct {
        ID         string `gorm:"primary_key; unique; json:id"`
        Generation uint32 `gorm:"type:integer; column:generation;" json:"generation" `
        // Additional gorm type jsonb set, if not present causes field to be bytea
        SwitchAttrs SwitchAttr `sql:"type:jsonb; not null; column:Switch_attrs;" gorm:"type:jsonb; json:switchAttrs"`
    }
    

    SwitchAttr添加这个

    type SwitchAttr struct {
        data struct {
            ID   *int    `json:"id"`
            Generation *string `json:"generation"`
            IDs []string `json:"IDs"`
        } `json:"data"`
    }
    
    // Column JSONB field 
    func (a SwitchAttr) Value() (driver.Value, error) {
        return json.Marshal(a)
    }
    
    // simply decodes a JSON-encoded value into the struct fields.
    func (a *SwitchAttr) Scan(value interface{}) error {
        b, ok := value.([]byte)
        if !ok {
            return errors.New("type assertion to []byte failed")
        }
    
        return json.Unmarshal(b, &a)
    }
    

    对于查询,

    db = db.Where("switchAttrs @> '{"data":{"IDs":<pass_your_array_of_string>}}'::jsonb").Find(&switches)
    

    【讨论】:

    • 真的必须修改 switchattrs 吗?我有很多属性在 switch_attrs 中存储为 jsonb,这就是我解组的方式。 ``` 开关 := make([]Switch, result.RowsAffected) for i, hciSwitch := range dbSwitches { unmarshalErr := json.Unmarshal(SwitchAttrs, &switches[i])```开关的结构如下
    • type Switch struct { CustomerID string Generation int64 ID string IDs string SwitchName string ResourceURI string Type string FirmwareVersion string }
    • 抱歉缩进不好,在评论部分提供代码真的很难..发布问题时很容易
    • 我的观点是,即使在我们到达编组/解组步骤之前,查询也会失败。为什么我不能像我在问题中粘贴的那样进行查询.. 我想使用 switch_attrs->Ids 方式。如果这些查询需要修改,有人可以纠正我..
    • is it really mandatory to modify the switchattrs,显然不是,但对于这个解决方案,它是必须的
    猜你喜欢
    • 1970-01-01
    • 2021-08-31
    • 1970-01-01
    • 2021-11-29
    • 1970-01-01
    • 2021-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多