Skip to content

Commit 7dad93e

Browse files
authored
add cmd: geosearch, geosearchstore (#1836)
* add cmd: geosearch, geosearchstore Signed-off-by: monkey92t <golang@88.com> * GeoSearchQuery and GeoSearchLocationQuery changed to pointer passing Signed-off-by: monkey92t <golang@88.com>
1 parent 437184b commit 7dad93e

File tree

3 files changed

+415
-0
lines changed

3 files changed

+415
-0
lines changed

command.go

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2637,6 +2637,188 @@ func newGeoLocationParser(q *GeoRadiusQuery) proto.MultiBulkParse {
26372637

26382638
//------------------------------------------------------------------------------
26392639

2640+
// GeoSearchQuery is used for GEOSearch/GEOSearchStore command query.
2641+
type GeoSearchQuery struct {
2642+
Member string
2643+
2644+
// Latitude and Longitude when using FromLonLat option.
2645+
Longitude float64
2646+
Latitude float64
2647+
2648+
// Distance and unit when using ByRadius option.
2649+
// Can use m, km, ft, or mi. Default is km.
2650+
Radius float64
2651+
RadiusUnit string
2652+
2653+
// Height, width and unit when using ByBox option.
2654+
// Can be m, km, ft, or mi. Default is km.
2655+
BoxWidth float64
2656+
BoxHeight float64
2657+
BoxUnit string
2658+
2659+
// Can be ASC or DESC. Default is no sort order.
2660+
Sort string
2661+
Count int
2662+
CountAny bool
2663+
}
2664+
2665+
type GeoSearchLocationQuery struct {
2666+
GeoSearchQuery
2667+
2668+
WithCoord bool
2669+
WithDist bool
2670+
WithHash bool
2671+
}
2672+
2673+
type GeoSearchStoreQuery struct {
2674+
GeoSearchQuery
2675+
2676+
// When using the StoreDist option, the command stores the items in a
2677+
// sorted set populated with their distance from the center of the circle or box,
2678+
// as a floating-point number, in the same unit specified for that shape.
2679+
StoreDist bool
2680+
}
2681+
2682+
func geoSearchLocationArgs(q *GeoSearchLocationQuery, args []interface{}) []interface{} {
2683+
args = geoSearchArgs(&q.GeoSearchQuery, args)
2684+
2685+
if q.WithCoord {
2686+
args = append(args, "withcoord")
2687+
}
2688+
if q.WithDist {
2689+
args = append(args, "withdist")
2690+
}
2691+
if q.WithHash {
2692+
args = append(args, "withhash")
2693+
}
2694+
2695+
return args
2696+
}
2697+
2698+
func geoSearchArgs(q *GeoSearchQuery, args []interface{}) []interface{} {
2699+
if q.Member != "" {
2700+
args = append(args, "frommember", q.Member)
2701+
} else {
2702+
args = append(args, "fromlonlat", q.Longitude, q.Latitude)
2703+
}
2704+
2705+
if q.Radius > 0 {
2706+
if q.RadiusUnit == "" {
2707+
q.RadiusUnit = "km"
2708+
}
2709+
args = append(args, "byradius", q.Radius, q.RadiusUnit)
2710+
} else {
2711+
if q.BoxUnit == "" {
2712+
q.BoxUnit = "km"
2713+
}
2714+
args = append(args, "bybox", q.BoxWidth, q.BoxHeight, q.BoxUnit)
2715+
}
2716+
2717+
if q.Sort != "" {
2718+
args = append(args, q.Sort)
2719+
}
2720+
2721+
if q.Count > 0 {
2722+
args = append(args, "count", q.Count)
2723+
if q.CountAny {
2724+
args = append(args, "any")
2725+
}
2726+
}
2727+
2728+
return args
2729+
}
2730+
2731+
type GeoSearchLocationCmd struct {
2732+
baseCmd
2733+
2734+
opt *GeoSearchLocationQuery
2735+
val []GeoLocation
2736+
}
2737+
2738+
var _ Cmder = (*GeoSearchLocationCmd)(nil)
2739+
2740+
func NewGeoSearchLocationCmd(
2741+
ctx context.Context, opt *GeoSearchLocationQuery, args ...interface{},
2742+
) *GeoSearchLocationCmd {
2743+
return &GeoSearchLocationCmd{
2744+
baseCmd: baseCmd{
2745+
ctx: ctx,
2746+
args: args,
2747+
},
2748+
opt: opt,
2749+
}
2750+
}
2751+
2752+
func (cmd *GeoSearchLocationCmd) Val() []GeoLocation {
2753+
return cmd.val
2754+
}
2755+
2756+
func (cmd *GeoSearchLocationCmd) Result() ([]GeoLocation, error) {
2757+
return cmd.val, cmd.err
2758+
}
2759+
2760+
func (cmd *GeoSearchLocationCmd) String() string {
2761+
return cmdString(cmd, cmd.val)
2762+
}
2763+
2764+
func (cmd *GeoSearchLocationCmd) readReply(rd *proto.Reader) error {
2765+
n, err := rd.ReadArrayLen()
2766+
if err != nil {
2767+
return err
2768+
}
2769+
2770+
cmd.val = make([]GeoLocation, n)
2771+
for i := 0; i < n; i++ {
2772+
_, err = rd.ReadArrayLen()
2773+
if err != nil {
2774+
return err
2775+
}
2776+
2777+
var loc GeoLocation
2778+
2779+
loc.Name, err = rd.ReadString()
2780+
if err != nil {
2781+
return err
2782+
}
2783+
if cmd.opt.WithDist {
2784+
loc.Dist, err = rd.ReadFloatReply()
2785+
if err != nil {
2786+
return err
2787+
}
2788+
}
2789+
if cmd.opt.WithHash {
2790+
loc.GeoHash, err = rd.ReadIntReply()
2791+
if err != nil {
2792+
return err
2793+
}
2794+
}
2795+
if cmd.opt.WithCoord {
2796+
nn, err := rd.ReadArrayLen()
2797+
if err != nil {
2798+
return err
2799+
}
2800+
if nn != 2 {
2801+
return fmt.Errorf("got %d coordinates, expected 2", nn)
2802+
}
2803+
2804+
loc.Longitude, err = rd.ReadFloatReply()
2805+
if err != nil {
2806+
return err
2807+
}
2808+
loc.Latitude, err = rd.ReadFloatReply()
2809+
if err != nil {
2810+
return err
2811+
}
2812+
}
2813+
2814+
cmd.val[i] = loc
2815+
}
2816+
2817+
return nil
2818+
}
2819+
2820+
//------------------------------------------------------------------------------
2821+
26402822
type GeoPos struct {
26412823
Longitude, Latitude float64
26422824
}

commands.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,9 @@ type Cmdable interface {
383383
GeoRadiusStore(ctx context.Context, key string, longitude, latitude float64, query *GeoRadiusQuery) *IntCmd
384384
GeoRadiusByMember(ctx context.Context, key, member string, query *GeoRadiusQuery) *GeoLocationCmd
385385
GeoRadiusByMemberStore(ctx context.Context, key, member string, query *GeoRadiusQuery) *IntCmd
386+
GeoSearch(ctx context.Context, key string, q *GeoSearchQuery) *StringSliceCmd
387+
GeoSearchLocation(ctx context.Context, key string, q *GeoSearchLocationQuery) *GeoSearchLocationCmd
388+
GeoSearchStore(ctx context.Context, key, store string, q *GeoSearchStoreQuery) *IntCmd
386389
GeoDist(ctx context.Context, key string, member1, member2, unit string) *FloatCmd
387390
GeoHash(ctx context.Context, key string, members ...string) *StringSliceCmd
388391
}
@@ -3347,6 +3350,38 @@ func (c cmdable) GeoRadiusByMemberStore(
33473350
return cmd
33483351
}
33493352

3353+
func (c cmdable) GeoSearch(ctx context.Context, key string, q *GeoSearchQuery) *StringSliceCmd {
3354+
args := make([]interface{}, 0, 13)
3355+
args = append(args, "geosearch", key)
3356+
args = geoSearchArgs(q, args)
3357+
cmd := NewStringSliceCmd(ctx, args...)
3358+
_ = c(ctx, cmd)
3359+
return cmd
3360+
}
3361+
3362+
func (c cmdable) GeoSearchLocation(
3363+
ctx context.Context, key string, q *GeoSearchLocationQuery,
3364+
) *GeoSearchLocationCmd {
3365+
args := make([]interface{}, 0, 16)
3366+
args = append(args, "geosearch", key)
3367+
args = geoSearchLocationArgs(q, args)
3368+
cmd := NewGeoSearchLocationCmd(ctx, q, args...)
3369+
_ = c(ctx, cmd)
3370+
return cmd
3371+
}
3372+
3373+
func (c cmdable) GeoSearchStore(ctx context.Context, key, store string, q *GeoSearchStoreQuery) *IntCmd {
3374+
args := make([]interface{}, 0, 15)
3375+
args = append(args, "geosearchstore", store, key)
3376+
args = geoSearchArgs(&q.GeoSearchQuery, args)
3377+
if q.StoreDist {
3378+
args = append(args, "storedist")
3379+
}
3380+
cmd := NewIntCmd(ctx, args...)
3381+
_ = c(ctx, cmd)
3382+
return cmd
3383+
}
3384+
33503385
func (c cmdable) GeoDist(
33513386
ctx context.Context, key string, member1, member2, unit string,
33523387
) *FloatCmd {

0 commit comments

Comments
 (0)