192 lines
4.7 KiB
Go
192 lines
4.7 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/paulmach/osm"
|
|
"github.com/paulmach/osm/osmpbf"
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
"go.mongodb.org/mongo-driver/mongo"
|
|
"go.mongodb.org/mongo-driver/mongo/options"
|
|
"go.mongodb.org/mongo-driver/x/bsonx"
|
|
)
|
|
|
|
func main() {
|
|
dbconnection := flag.String("dbconnection", "mongodb://localhost:27017", "Mongo database name")
|
|
dbname := flag.String("dbname", "osm", "Mongo database name")
|
|
osmfile := flag.String("osmfile", "", "OSM file")
|
|
flag.Parse()
|
|
ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
|
|
client, err := mongo.Connect(ctx, options.Client().ApplyURI(*dbconnection))
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer client.Disconnect(context.Background())
|
|
db := client.Database(*dbname)
|
|
if err := read(db, *osmfile); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
}
|
|
|
|
func read(db *mongo.Database, file string) error {
|
|
nodes := db.Collection("nodes")
|
|
_, _ = nodes.Indexes().CreateOne(
|
|
context.Background(),
|
|
mongo.IndexModel{
|
|
Keys: bsonx.Doc{{"osm_id", bsonx.Int32(1)}},
|
|
Options: options.Index().SetUnique(true).SetSparse(true).SetBackground(true),
|
|
},
|
|
)
|
|
_, _ = nodes.Indexes().CreateOne(
|
|
context.Background(),
|
|
mongo.IndexModel{
|
|
Keys: bsonx.Doc{{"coords", bsonx.Int32(1)}},
|
|
Options: options.Index().SetSphereVersion(2).SetSparse(true).SetBackground(true),
|
|
},
|
|
)
|
|
|
|
ways := db.Collection("ways")
|
|
_, _ = ways.Indexes().CreateOne(
|
|
context.Background(),
|
|
mongo.IndexModel{
|
|
Keys: bsonx.Doc{{"osm_id", bsonx.Int32(1)}},
|
|
Options: options.Index().SetUnique(true).SetSparse(true).SetBackground(true),
|
|
},
|
|
)
|
|
_, _ = ways.Indexes().CreateOne(
|
|
context.Background(),
|
|
mongo.IndexModel{
|
|
Keys: bsonx.Doc{{"nodes", bsonx.Int32(1)}},
|
|
Options: options.Index().SetSparse(true).SetBackground(true),
|
|
},
|
|
)
|
|
|
|
relations := db.Collection("relations")
|
|
_, _ = relations.Indexes().CreateOne(
|
|
context.Background(),
|
|
mongo.IndexModel{
|
|
Keys: bsonx.Doc{{"osm_id", bsonx.Int32(1)}},
|
|
Options: options.Index().SetUnique(true).SetSparse(true).SetBackground(true),
|
|
},
|
|
)
|
|
_, _ = relations.Indexes().CreateOne(
|
|
context.Background(),
|
|
mongo.IndexModel{
|
|
Keys: bsonx.Doc{{"members.ref", bsonx.Int32(1)}},
|
|
Options: options.Index().SetUnique(true).SetSparse(true).SetBackground(true),
|
|
},
|
|
)
|
|
_, _ = relations.Indexes().CreateOne(
|
|
context.Background(),
|
|
mongo.IndexModel{
|
|
Keys: bsonx.Doc{{"members.coords", bsonx.Int32(1)}},
|
|
Options: options.Index().SetSphereVersion(2).SetSparse(true).SetBackground(true),
|
|
},
|
|
)
|
|
|
|
f, err := os.Open(file)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer f.Close()
|
|
|
|
opts := (new(options.ReplaceOptions)).SetUpsert(true)
|
|
nc := 0
|
|
wc := 0
|
|
rc := 0
|
|
|
|
scanner := osmpbf.New(context.Background(), f, 3)
|
|
defer scanner.Close()
|
|
|
|
for scanner.Scan() {
|
|
o := scanner.Object()
|
|
switch o := o.(type) {
|
|
case *osm.Way:
|
|
nodes := make([]int64, 0, len(o.Nodes))
|
|
for _, v := range o.Nodes {
|
|
nodes = append(nodes, int64(v.ID))
|
|
}
|
|
w := Way{
|
|
OsmID: int64(o.ID),
|
|
Tags: convertTags(o.Tags),
|
|
Nodes: nodes,
|
|
Timestamp: o.Timestamp,
|
|
Version: o.Version,
|
|
Visible: o.Visible,
|
|
}
|
|
if _, err = ways.ReplaceOne(context.Background(), bson.M{"osm_id": int64(o.ID)}, w, opts); err != nil {
|
|
return err
|
|
}
|
|
wc++
|
|
case *osm.Node:
|
|
n := Node{
|
|
OsmID: int64(o.ID),
|
|
Location: Coords{
|
|
Type: "Point",
|
|
Coordinates: []float64{
|
|
o.Lon,
|
|
o.Lat,
|
|
}},
|
|
Tags: convertTags(o.Tags),
|
|
Version: o.Version,
|
|
Timestamp: o.Timestamp,
|
|
Visible: o.Visible,
|
|
}
|
|
if _, err = nodes.ReplaceOne(context.Background(), bson.M{"osm_id": int64(o.ID)}, n, opts); err != nil {
|
|
return err
|
|
}
|
|
nc++
|
|
case *osm.Relation:
|
|
members := make([]Member, len(o.Members))
|
|
for _, v := range o.Members {
|
|
members = append(members, Member{
|
|
Type: v.Type,
|
|
Version: v.Version,
|
|
Orientation: v.Orientation,
|
|
Ref: v.Ref,
|
|
Role: v.Role,
|
|
Location: Coords{
|
|
Type: "Point",
|
|
Coordinates: []float64{
|
|
v.Lon,
|
|
v.Lat,
|
|
}},
|
|
})
|
|
}
|
|
r := Relation{
|
|
OsmID: int64(o.ID),
|
|
Tags: convertTags(o.Tags),
|
|
Version: o.Version,
|
|
Timestamp: o.Timestamp,
|
|
Visible: o.Visible,
|
|
Members: members,
|
|
}
|
|
if _, err = relations.ReplaceOne(context.Background(), bson.M{"osm_id": int64(o.ID)}, r, opts); err != nil {
|
|
return err
|
|
}
|
|
rc++
|
|
}
|
|
fmt.Printf("\rNodes: %d Ways: %d Relations: %d", nc, wc, rc)
|
|
}
|
|
|
|
scanErr := scanner.Err()
|
|
if scanErr != nil {
|
|
return scanErr
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func convertTags(tags osm.Tags) map[string]string {
|
|
result := make(map[string]string, len(tags))
|
|
for _, t := range tags {
|
|
result[t.Key] = t.Value
|
|
}
|
|
return result
|
|
}
|