Я много искал, и хотя я могу найти кучу хороших статей, которые объясняют, как работать с пакетом pq напрямую. Я не могу работать в контексте go-gorm и диалекта postgresql.
Если в Checks.go я использую ChecksMap, он не позволяет мне вставлять, но позволяет найти. Если я использую postgres.jsonb, он позволяет мне вставлять и запрашивать, но найденные записи будут jsonb.
Горм использует структуру указателя для определения таблицы и схемы БД. Это вызывает головную боль при использовании универсальной утилиты searchHandler, которая возвращает ответ json от API. Для любых типов, отличных от jsonb, gorm работает с соответствующими структурами и использует теги json, но для jsonb, поскольку он не имеет ссылки на «структуру» jsonb, он не может использовать теги json. Это приводит к тому, что возвращаемый API json имеет ключи с заглавной буквы.
{
results: {
id: "123",
someId: "456",
results: [
{
Description: "foobar"
}
]
}
}
Есть ли элегантный способ справиться с такими вещами, чтобы столбец результатов jsonb имел правильную структуру и использовал теги json в нижнем регистре? Я просто пытаюсь делать то, чего не следует делать в контексте гурманов?
POSTGRESQL DDL
CREATE TABLE checks (
id text,
some_id text,
results jsonb
);
Checks.go
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
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
var checks Checks
err := db.Find(&checks).Error
// ... some error handling
searchHandler.go
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),
})
}
}
driver.Valuer
на приемнике значения, а не на указателе. То есть поменятьfunc (cm *ChecksMap) Value() ...
наfunc (cm ChecksMap) Value() ...
, вставлять все равно не удастся, если вы это сделаете? И если он по-прежнему не работает, можете ли вы показать, в чем ошибка, и если ошибки нет, можете ли вы показать, как вы реализовали методValue()
? - person mkopriva   schedule 03.09.2019