首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >go-gorm postgres方言:为jsonb插入和查找正确使用json标记管理结构

go-gorm postgres方言:为jsonb插入和查找正确使用json标记管理结构
EN

Stack Overflow用户
提问于 2019-09-03 15:43:36
回答 1查看 2K关注 0票数 1

一直在做大量的搜索,虽然我可以找到一堆很好的文章来解释如何直接使用pq包。我无法在go-gorm和postgresql方言的上下文中工作。

如果在checks.go中使用ChecksMap,它不允许我插入,而是会让我找到。如果我使用postgres.jsonb,它允许我插入和查询,但是找到的记录将是jsonb的。

Gorm使用指针的结构来确定db表和模式。当使用泛型searchHandler实用程序从API返回json响应时,这会引起头痛。对于任何非jsonb类型,gorm使用正确的结构并使用json标记,但是对于jsonb,因为它没有引用jsonb的"struct“,所以它不能使用json标记。这将导致返回API json具有大写键。

代码语言:javascript
复制
{
   results: {
      id: "123",
      someId: "456",
      results: [
         {
            Description: "foobar"
         }
      ]
   }
}

是否有一种优雅的方法来处理这类事情,以便jsonb结果列具有正确的结构并使用低限值的json标记?我只是想做一些不该在go-gorm的背景下做的事情吗?

POSTGRESQL

代码语言:javascript
复制
CREATE TABLE checks (
   id        text,
   some_id   text,
   results   jsonb
);

checks.go

代码语言:javascript
复制
type CheckRules struct {
   Description   string `json:"description"`
}

type ChecksMap   map[string]CheckRules

type Checks struct {
   ID            string           `gorm: "primary_key", json:"id"`
   SomeID        *string          `json:"someId"`
   Results       postgres.jsonb   `json:"results"`                   // <-- this
   // results    ChecksMap        `gorm:"type:jsonb" json:"results"` // <-- or this
}

// func (cm *ChecksMap) Value() (driver.Value, error) {...}
// func (cm *ChecksMap) Scan(val interface{}) error {...}

insertChecks.go

代码语言:javascript
复制
var resultsVal = getResultsValue() // simplified
resJson, _ := json.Marshal(resultsVal)

checks := Checks{
   SomeID: "123",
   Results: postgres.Jsonb{ RawMessage: json.RawMessage(resJson) }
}

err := db.Create(&checks).Error
// ... some error handling

getChecks.go

代码语言:javascript
复制
var checks Checks

err := db.Find(&checks).Error
// ... some error handling

searchHandler.go

代码语言:javascript
复制
func SearchHandler(db *gorm.DB, model, results interface{}) func(c echo.Context) error {
   return func(c echo.Context) error {
      err := db.Find(results).Error
      // ... some error handling

      jsnRes, _ := json.Marshal(results) // <-- uppercase "keys"

      return c.JSON(http.StatusOK, struct {
         Results interface{} `json:"results"`
      }{
         Results: string(jsnRes),
      })
   }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-09-03 17:20:07

您可以使用自定义的ChecksMap类型,但在其值接收器上实现driver.Valuer接口,而不是指针接收者。

因此,与其:

代码语言:javascript
复制
func (cm *ChecksMap) Value() (driver.Value, error) { ...

你可以这样写:

代码语言:javascript
复制
func (cm ChecksMap) Value() (driver.Value, error) {
    if cm == nil {
        return nil, nil
    }
    return json.Marshal(cm)
}

或者,您可能可以使其与指针实现一起工作,但随后您必须将该字段转换为指针,例如:

代码语言:javascript
复制
type Checks struct {
   ID      string     `gorm: "primary_key", json:"id"`
   SomeID  *string    `json:"someId"`
   Results *ChecksMap `json:"results"`
}

(虽然我还没有测试过这个,所以我不能百分之百地确定gorm将如何处理这个案件)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57774957

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档