Skip to content

Instantly share code, notes, and snippets.

@wangrenjun
Created February 5, 2021 09:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wangrenjun/6579c7c58bc8bfe26b47848fd68fadcd to your computer and use it in GitHub Desktop.
Save wangrenjun/6579c7c58bc8bfe26b47848fd68fadcd to your computer and use it in GitHub Desktop.
Go loading data and coordinates from GeoJson file to PostgreSQL using Gorm.
package main
import (
"flag"
"fmt"
"io/ioutil"
"strconv"
"time"
geojson "github.com/paulmach/go.geojson"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
func main() {
flag.Parse()
rawFeatureJSON, err := ioutil.ReadFile(*file)
if err != nil {
panic(err)
}
fc, err := geojson.UnmarshalFeatureCollection(rawFeatureJSON)
if err != nil {
panic(err)
}
gormdb := open()
for _, f := range fc.Features {
fmt.Printf("Name: %v\n\n", f.Properties["name"])
fmt.Printf("Type: %v\n\n", f.Geometry.Type)
name := f.Properties["name"].(string)
switch {
case f.Geometry.Type == "Polygon":
coor := polygonCoordinates(f.Geometry.Polygon)
coor = fmt.Sprintf("POLYGON(%s)\n", coor)
insert(gormdb, name, coor)
case f.Geometry.Type == "GeometryCollection":
coor := "MULTIPOLYGON("
for i := range f.Geometry.Geometries {
coor += "("
coor += polygonCoordinates(f.Geometry.Geometries[i].Polygon)
coor += "),"
}
coor = coor[:len(coor)-1]
coor += ")"
insert(gormdb, name, coor)
break
default:
panic(f.Geometry.Type)
}
}
fmt.Printf("List the items just inserted:\n")
list(gormdb)
}
var dsn = flag.String("dsn", "", "PostgreSQL DSN")
var file = flag.String("file", "", ".geojson")
type Grid struct {
Id int64 `gorm:"primarykey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
Name string
}
func open() (gormdb *gorm.DB) {
gormdb, err := gorm.Open(postgres.Open(*dsn), &gorm.Config{
Logger: logger.Default.LogMode(logger.Info),
})
if err != nil {
panic(err)
}
gormdb.AutoMigrate(&Grid{})
gormdb.Exec("ALTER TABLE grids ADD COLUMN IF NOT EXISTS geom geometry")
gormdb.Exec("CREATE INDEX IF NOT EXISTS grids_idx_geom ON grids USING GIST(geom)")
return
}
func insert(gormdb *gorm.DB, name, coor string) {
grid := Grid{
Name: name,
}
tx := gormdb.Begin()
err := tx.Create(&grid).Error
if err != nil {
fmt.Printf("%s: %v\n", name, err)
tx.Rollback()
panic(err)
}
err = tx.Exec("UPDATE grids SET geom = '"+coor+"' WHERE id = ?", grid.Id).Error
if err != nil {
fmt.Printf("%s: %v\n", name, err)
tx.Rollback()
panic(err)
}
err = tx.Commit().Error
if err != nil {
fmt.Printf("%s: %v\n", name, err)
panic(err)
}
}
func list(gormdb *gorm.DB) {
rows, err := gormdb.Table("grids").Select("id, name, ST_AsGeojson(geom) AS coordinates").Rows()
if err != nil {
panic(err)
}
defer rows.Close()
for rows.Next() {
var id int64
var name, coordinates string
rows.Scan(&id, &name, &coordinates)
fmt.Printf("%d: %s: %s\n", id, name, coordinates)
}
}
func polygonCoordinates(polygon [][][]float64) (coor string) {
for i := range polygon {
coor += "("
for j := range polygon[i] {
if len(polygon[i][j]) > 1 {
long := strconv.FormatFloat(polygon[i][j][0], 'f', -1, 64)
lat := strconv.FormatFloat(polygon[i][j][1], 'f', -1, 64)
coor += long + " " + lat + ","
}
}
coor = coor[:len(coor)-1]
coor += "),"
}
coor = coor[:len(coor)-1]
return
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment