I'm having trouble saving a PostGIS point with entgo and pgx.
I try to use the pgtype.Point type from pgx, the schema looks like this:
// Fields of the Event.
func (EventSchema) Fields() []ent.Field {
return []ent.Field{
field.UUID("id", uuid.UUID{}).Immutable().
Annotations(&entsql.Annotation{
Default: "gen_random_uuid()"
}),
field.Other("location", &pgtype.Point{}).
SchemaType(map[string]string{
dialect.Postgres: "geometry(point, 4326)"
}).StorageKey("location").Optional(),
}
}
In the database, the type of "location" is also geometry(point, 4326)
.
The query to create:
db.EventSchema.Create().SetLocation(point).Save()
leads to the error: ERROR: parse error - invalid geometry (SQLSTATE XX000)
Can't I just use pgtype.Point here, but do some formatting? Or does anyone have a working example with a different point type, e.g. with go-geom?
Thanks for your help!
This solution worked for me, may it help you too.
schema
field.Other("location", &database.GeoJson{}).
SchemaType(map[string]string{
dialect.Postgres: "geometry(point, 4326)",
}).StorageKey("location").Optional(),
custom GeoJson type based on geojson.Geometry
type GeoJson struct {
*geojson.Geometry
}
func (t *GeoJson) Value() (driver.Value, error) {
geometry, err := t.Decode()
if err != nil {
logging.Logger.Debug(err)
return nil, err
}
encodedGeometry, err := ewkbhex.Encode(geometry, binary.LittleEndian)
if err != nil {
logging.Logger.Debug(err)
return nil, err
}
return encodedGeometry, nil
}
func (t *GeoJson) Scan(value interface{}) error {
// handle nil
if value == nil {
t = nil
return nil
}
// parse as string
stringValue, ok := value.(string)
if !ok {
return errors.New("value is no string")
}
geometry, err := ewkbhex.Decode(stringValue)
if err != nil {
return err
}
geometryAsBytes, err := geojson.Marshal(geometry)
if err != nil {
return err
}
var geoJson GeoJson
if err := json.Unmarshal(geometryAsBytes, &geoJson); err != nil {
return err
}
*t = geoJson
return nil
}
example json payload
"location": {
"type": "Point",
"coordinates": [22.666460, 31.180481]
}