github.com/micro/go-micro/examples@v0.0.0-20210105173217-bf4ab679e18b/booking/srv/geo/main.go (about)

     1  package main
     2  
     3  import (
     4  	"encoding/json"
     5  	"log"
     6  
     7  	"github.com/hailocab/go-geoindex"
     8  	"github.com/micro/go-micro/examples/booking/data"
     9  	"github.com/micro/go-micro/examples/booking/srv/geo/proto"
    10  
    11  	"context"
    12  	"golang.org/x/net/trace"
    13  
    14  	"github.com/micro/go-micro/v2"
    15  	"github.com/micro/go-micro/v2/metadata"
    16  )
    17  
    18  const (
    19  	maxSearchRadius  = 10
    20  	maxSearchResults = 5
    21  )
    22  
    23  type point struct {
    24  	Pid  string  `json:"hotelId"`
    25  	Plat float64 `json:"lat"`
    26  	Plon float64 `json:"lon"`
    27  }
    28  
    29  // Implement Point interface
    30  func (p *point) Lat() float64 { return p.Plat }
    31  func (p *point) Lon() float64 { return p.Plon }
    32  func (p *point) Id() string   { return p.Pid }
    33  
    34  type Geo struct {
    35  	index *geoindex.ClusteringIndex
    36  }
    37  
    38  // Nearby returns all hotels within a given distance.
    39  func (s *Geo) Nearby(ctx context.Context, req *geo.Request, rsp *geo.Result) error {
    40  	md, _ := metadata.FromContext(ctx)
    41  	traceID := md["traceID"]
    42  
    43  	if tr, ok := trace.FromContext(ctx); ok {
    44  		tr.LazyPrintf("traceID %s", traceID)
    45  	}
    46  
    47  	// create center point for query
    48  	center := &geoindex.GeoPoint{
    49  		Pid:  "",
    50  		Plat: float64(req.Lat),
    51  		Plon: float64(req.Lon),
    52  	}
    53  
    54  	// find points around center point
    55  	points := s.index.KNearest(center, maxSearchResults, geoindex.Km(maxSearchRadius), func(p geoindex.Point) bool {
    56  		return true
    57  	})
    58  
    59  	for _, p := range points {
    60  		rsp.HotelIds = append(rsp.HotelIds, p.Id())
    61  	}
    62  	return nil
    63  }
    64  
    65  // newGeoIndex returns a geo index with points loaded
    66  func newGeoIndex(path string) *geoindex.ClusteringIndex {
    67  	file := data.MustAsset(path)
    68  
    69  	// unmarshal json points
    70  	var points []*point
    71  	if err := json.Unmarshal(file, &points); err != nil {
    72  		log.Fatalf("Failed to load hotels: %v", err)
    73  	}
    74  
    75  	// add points to index
    76  	index := geoindex.NewClusteringIndex()
    77  	for _, point := range points {
    78  		index.Add(point)
    79  	}
    80  	return index
    81  }
    82  
    83  func main() {
    84  	service := micro.NewService(
    85  		micro.Name("go.micro.srv.geo"),
    86  	)
    87  
    88  	service.Init()
    89  
    90  	geo.RegisterGeoHandler(service.Server(), &Geo{
    91  		index: newGeoIndex("data/locations.json"),
    92  	})
    93  
    94  	service.Run()
    95  }