postgresql - 使用 Gorm 插入和选择 PostGIS 几何
问题描述
我一直在尝试找到一种使用 Golang 插入和检索几何类型的方法,特别是库gorm。我还尝试使用为几何定义不同类型的库orb,并提供不同格式之间的编码/解码。
Orb已经为每种类型实现了方法Scan()
。Value()
这允许 goInsert()
和Scan()
函数使用原始类型以外的类型。然而,Orb 希望使用以众所周知的二进制 (WKB) 格式表示的几何图形。
orb 文档显示要完成此操作,您应该简单地将字段包装在 PostGIS 函数中ST_AsBinary()
,并ST_GeomFromWKB()
分别用于查询和插入。例如,一个表定义为:
_, err = db.Exec(`
CREATE TABLE IF NOT EXISTS orbtest (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
geom geometry(POLYGON, 4326) NOT NULL
);
`)
你可以这样做:
rows, err := db.Query("SELECT id, name, ST_AsBinary(geom) FROM orbtest LIMIT 1")
对于插入(其中 p 是一个 orb.Point):
db.Exec("INSERT INTO orbtest (id, name, geom) VALUES ($1, $2, ST_GeomFromWKB($3))", 1, "Test", wkb.Value(p))
这是我的问题:通过使用 GORM,我无法使用这些函数构建这些查询。GORM 会自动将值插入到给定结构的数据库中,并将数据扫描到结构的整个层次结构中。这些Scan()
和Value()
方法在幕后被调用,不受我的控制。
尝试将二进制数据直接插入几何列是行不通的,直接查询几何列将给出十六进制的结果。
我尝试了多种数据库方法来解决这个问题。我尝试创建在几何列上自动调用所需函数的视图。这适用于查询,但不适用于插入。
是否可以制作某种触发器或规则来自动调用传入/传出数据所需的函数?
我还应该注意,我正在开发的库完全独立于数据和模式,所以我没有对任何类型的查询进行硬编码的奢侈。我当然可以编写一个扫描整个数据模型并从头开始生成查询的函数,但如果有更好的选择,我会更喜欢。
有谁知道在 SQL 中进行这项工作的方法?仅通过查询列本身就能够自动调用列上的函数?
任何建议将不胜感激。
解决方案
我将@robbieperry22 的答案与不同的编码库一起使用,发现我根本不需要修改字节。
包括要点供参考。
import "github.com/twpayne/go-geom/encoding/geojson"
type EWKBGeomPoint geom.Point
func (g *EWKBGeomPoint) Scan(input interface{}) error {
gt, err := ewkb.Unmarshal(input.([]byte))
if err != nil {
return err
}
g = gt.(*EWKBGeomPoint)
return nil
}
func (g EWKBGeomPoint) Value() (driver.Value, error) {
b := geom.Point(g)
bp := &b
ewkbPt := ewkb.Point{Point: bp.SetSRID(4326)}
return ewkbPt.Value()
}
type Track struct {
gorm.Model
GeometryPoint EWKBGeomPoint `gorm:"column:geom"`
}
然后在表设置/迁移部分使用了一些自定义:
err = db.Exec(`CREATE TABLE IF NOT EXISTS tracks (
id SERIAL PRIMARY KEY,
geom geometry(POINT, 4326) NOT NULL
);`).Error
if err != nil {
return err
}
err = gormigrate.New(db, gormigrate.DefaultOptions, []*gormigrate.Migration{
{
ID: "init",
Migrate: func(tx *gorm.DB) error {
return tx.CreateTable(
Tables...,
).Error
},
},
{
ID: "tracks_except_geom",
Migrate: func(tx *gorm.DB) error {
return db.AutoMigrate(Track{}).Error
},
},
}).Migrate()
推荐阅读
- java - 安装 JRE 8 和 Elasticsearch 7.3.1 后没有 jvm.options
- javascript - 如何定义可在所有 API 中使用的基本 url
- javascript - 循环通过api请求时插入失败仅执行第一个查询
- javascript - 如何执行 *ngFor 以从服务器获取所有数据?角度 7
- java - 扫描仪需要两个输入
- java - 如何实现一个引用主对象中定义的父对象的静态方法?
- symfony - PhpStorm 无法识别 KernelBrowser getResponse 函数
- reactjs - 我可以控制台记录我的状态,但我仍然得到“无法读取未定义的属性'数据'”。为什么?
- python - 如何从excel文件中更改xml值
- uwp - 在所有 3 个平台(x86、x64、ARM)中将 UWP 应用上传到 Microsoft Store