Mysql
 sql >> Base de données >  >> RDS >> Mysql

Travailler avec des données spatiales avec Gorm et MySQL

Voici une autre approche; utiliser l'encodage binaire.

Selon ce doc , MySQL stocke les valeurs de géométrie en utilisant 4 octets pour indiquer le SRID (ID de référence spatiale) suivi de la représentation WKB (Well Known Binary) de la valeur.

Ainsi, un type peut utiliser le codage WKB et ajouter et supprimer le préfixe de quatre octets dans les fonctions Value() et Scan(). La bibliothèque go-geom trouvée dans d'autres réponses contient un package d'encodage WKB, github.com/twpayne/go-geom/encoding/wkb.

Par exemple :

type MyPoint struct {
    Point wkb.Point
}

func (m *MyPoint) Value() (driver.Value, error) {
    value, err := m.Point.Value()
    if err != nil {
        return nil, err
    }

    buf, ok := value.([]byte)
    if !ok {
        return nil, fmt.Errorf("did not convert value: expected []byte, but was %T", value)
    }

    mysqlEncoding := make([]byte, 4)
    binary.LittleEndian.PutUint32(mysqlEncoding, 4326)
    mysqlEncoding = append(mysqlEncoding, buf...)

    return mysqlEncoding, err
}

func (m *MyPoint) Scan(src interface{}) error {
    if src == nil {
        return nil
    }

    mysqlEncoding, ok := src.([]byte)
    if !ok {
        return fmt.Errorf("did not scan: expected []byte but was %T", src)
    }

    var srid uint32 = binary.LittleEndian.Uint32(mysqlEncoding[0:4])

    err := m.Point.Scan(mysqlEncoding[4:])

    m.Point.SetSRID(int(srid))

    return err
}

Définir un Tag en utilisant le type MyPoint :

type Tag struct {
    Name string   `gorm:"type:varchar(50);primary_key"`
    Loc  *MyPoint `gorm:"column:loc"`
}

func (t Tag) String() string {
    return fmt.Sprintf("%s @ Point(%f, %f)", t.Name, t.Loc.Point.Coords().X(), t.Loc.Point.Coords().Y())
}

Création d'un tag en utilisant le type :

tag := &Tag{
    Name: "London",
    Loc: &MyPoint{
        wkb.Point{
            geom.NewPoint(geom.XY).MustSetCoords([]float64{0.1275, 51.50722}).SetSRID(4326),
        },
    },
}

err = db.Create(&tag).Error
if err != nil {
    log.Fatalf("create: %v", err)
}

Résultats MySQL :

mysql> describe tag;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| name  | varchar(50) | NO   | PRI | NULL    |       |
| loc   | geometry    | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+


mysql> select name, st_astext(loc) from tag;
+--------+------------------------+
| name   | st_astext(loc)         |
+--------+------------------------+
| London | POINT(0.1275 51.50722) |
+--------+------------------------+
  • (ArcGIS indique 4326 est la référence spatiale la plus courante pour stocker une donnée de référencement dans le monde entier. Il sert de valeur par défaut pour la base de données spatiale PostGIS et la norme GeoJSON. Il est également utilisé par défaut dans la plupart des bibliothèques de cartographie Web.)