mirror of https://github.com/go-redis/redis.git
Fix GeoRadius reply parsing.
This commit is contained in:
parent
0ddff681c2
commit
842ea553dc
36
command.go
36
command.go
|
@ -773,7 +773,7 @@ func (cmd *ClusterSlotCmd) readReply(cn *conn) error {
|
||||||
// GeoLocation is used with GeoAdd to add geospatial location.
|
// GeoLocation is used with GeoAdd to add geospatial location.
|
||||||
type GeoLocation struct {
|
type GeoLocation struct {
|
||||||
Name string
|
Name string
|
||||||
Longitude, Latitude, Distance float64
|
Longitude, Latitude, Dist float64
|
||||||
GeoHash int64
|
GeoHash int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -793,11 +793,39 @@ type GeoRadiusQuery struct {
|
||||||
type GeoLocationCmd struct {
|
type GeoLocationCmd struct {
|
||||||
baseCmd
|
baseCmd
|
||||||
|
|
||||||
|
q *GeoRadiusQuery
|
||||||
locations []GeoLocation
|
locations []GeoLocation
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGeoLocationCmd(args ...interface{}) *GeoLocationCmd {
|
func NewGeoLocationCmd(q *GeoRadiusQuery, args ...interface{}) *GeoLocationCmd {
|
||||||
return &GeoLocationCmd{baseCmd: baseCmd{_args: args, _clusterKeyPos: 1}}
|
args = append(args, q.Radius)
|
||||||
|
if q.Unit != "" {
|
||||||
|
args = append(args, q.Unit)
|
||||||
|
} else {
|
||||||
|
args = append(args, "km")
|
||||||
|
}
|
||||||
|
if q.WithCoord {
|
||||||
|
args = append(args, "WITHCOORD")
|
||||||
|
}
|
||||||
|
if q.WithDist {
|
||||||
|
args = append(args, "WITHDIST")
|
||||||
|
}
|
||||||
|
if q.WithGeoHash {
|
||||||
|
args = append(args, "WITHHASH")
|
||||||
|
}
|
||||||
|
if q.Count > 0 {
|
||||||
|
args = append(args, "COUNT", q.Count)
|
||||||
|
}
|
||||||
|
if q.Sort != "" {
|
||||||
|
args = append(args, q.Sort)
|
||||||
|
}
|
||||||
|
return &GeoLocationCmd{
|
||||||
|
baseCmd: baseCmd{
|
||||||
|
_args: args,
|
||||||
|
_clusterKeyPos: 1,
|
||||||
|
},
|
||||||
|
q: q,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *GeoLocationCmd) reset() {
|
func (cmd *GeoLocationCmd) reset() {
|
||||||
|
@ -818,7 +846,7 @@ func (cmd *GeoLocationCmd) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *GeoLocationCmd) readReply(cn *conn) error {
|
func (cmd *GeoLocationCmd) readReply(cn *conn) error {
|
||||||
reply, err := readArrayReply(cn, geoLocationSliceParser)
|
reply, err := readArrayReply(cn, newGeoLocationSliceParser(cmd.q))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cmd.err = err
|
cmd.err = err
|
||||||
return err
|
return err
|
||||||
|
|
35
commands.go
35
commands.go
|
@ -1722,41 +1722,16 @@ func (c *commandable) GeoAdd(key string, geoLocation ...*GeoLocation) *IntCmd {
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *commandable) geoRadius(args []interface{}, query *GeoRadiusQuery) *GeoLocationCmd {
|
func (c *commandable) GeoRadius(key string, longitude, latitude float64, query *GeoRadiusQuery) *GeoLocationCmd {
|
||||||
args = append(args, query.Radius)
|
cmd := NewGeoLocationCmd(query, "GEORADIUS", key, longitude, latitude)
|
||||||
if query.Unit != "" {
|
|
||||||
args = append(args, query.Unit)
|
|
||||||
} else {
|
|
||||||
args = append(args, "km")
|
|
||||||
}
|
|
||||||
if query.WithCoord {
|
|
||||||
args = append(args, "WITHCOORD")
|
|
||||||
}
|
|
||||||
if query.WithDist {
|
|
||||||
args = append(args, "WITHDIST")
|
|
||||||
}
|
|
||||||
if query.WithGeoHash {
|
|
||||||
args = append(args, "WITHHASH")
|
|
||||||
}
|
|
||||||
if query.Count > 0 {
|
|
||||||
args = append(args, "COUNT", query.Count)
|
|
||||||
}
|
|
||||||
if query.Sort != "" {
|
|
||||||
args = append(args, query.Sort)
|
|
||||||
}
|
|
||||||
cmd := NewGeoLocationCmd(args...)
|
|
||||||
c.Process(cmd)
|
c.Process(cmd)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *commandable) GeoRadius(key string, longitude, latitude float64, query *GeoRadiusQuery) *GeoLocationCmd {
|
|
||||||
args := []interface{}{"GEORADIUS", key, longitude, latitude}
|
|
||||||
return c.geoRadius(args, query)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *commandable) GeoRadiusByMember(key, member string, query *GeoRadiusQuery) *GeoLocationCmd {
|
func (c *commandable) GeoRadiusByMember(key, member string, query *GeoRadiusQuery) *GeoLocationCmd {
|
||||||
args := []interface{}{"GEORADIUSBYMEMBER", key, member}
|
cmd := NewGeoLocationCmd(query, "GEORADIUSBYMEMBER", key, member)
|
||||||
return c.geoRadius(args, query)
|
c.Process(cmd)
|
||||||
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *commandable) GeoDist(key string, member1, member2, unit string) *FloatCmd {
|
func (c *commandable) GeoDist(key string, member1, member2, unit string) *FloatCmd {
|
||||||
|
|
106
commands_test.go
106
commands_test.go
|
@ -2553,17 +2553,7 @@ var _ = Describe("Commands", func() {
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("Geo add and radius search", func() {
|
Describe("Geo add and radius search", func() {
|
||||||
|
BeforeEach(func() {
|
||||||
It("should add one geo location", func() {
|
|
||||||
geoAdd := client.GeoAdd(
|
|
||||||
"Sicily",
|
|
||||||
&redis.GeoLocation{Longitude: 13.361389, Latitude: 38.115556, Name: "Palermo"},
|
|
||||||
)
|
|
||||||
Expect(geoAdd.Err()).NotTo(HaveOccurred())
|
|
||||||
Expect(geoAdd.Val()).To(Equal(int64(1)))
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should add multiple geo locations", func() {
|
|
||||||
geoAdd := client.GeoAdd(
|
geoAdd := client.GeoAdd(
|
||||||
"Sicily",
|
"Sicily",
|
||||||
&redis.GeoLocation{Longitude: 13.361389, Latitude: 38.115556, Name: "Palermo"},
|
&redis.GeoLocation{Longitude: 13.361389, Latitude: 38.115556, Name: "Palermo"},
|
||||||
|
@ -2573,16 +2563,19 @@ var _ = Describe("Commands", func() {
|
||||||
Expect(geoAdd.Val()).To(Equal(int64(2)))
|
Expect(geoAdd.Val()).To(Equal(int64(2)))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("should not add same geo location", func() {
|
||||||
|
geoAdd := client.GeoAdd(
|
||||||
|
"Sicily",
|
||||||
|
&redis.GeoLocation{Longitude: 13.361389, Latitude: 38.115556, Name: "Palermo"},
|
||||||
|
)
|
||||||
|
Expect(geoAdd.Err()).NotTo(HaveOccurred())
|
||||||
|
Expect(geoAdd.Val()).To(Equal(int64(0)))
|
||||||
|
})
|
||||||
|
|
||||||
It("should search geo radius", func() {
|
It("should search geo radius", func() {
|
||||||
geoAdd := client.GeoAdd(
|
res, err := client.GeoRadius("Sicily", 15, 37, &redis.GeoRadiusQuery{
|
||||||
"Sicily",
|
Radius: 200,
|
||||||
&redis.GeoLocation{Longitude: 13.361389, Latitude: 38.115556, Name: "Palermo"},
|
}).Result()
|
||||||
&redis.GeoLocation{Longitude: 15.087269, Latitude: 37.502669, Name: "Catania"},
|
|
||||||
)
|
|
||||||
Expect(geoAdd.Err()).NotTo(HaveOccurred())
|
|
||||||
Expect(geoAdd.Val()).To(Equal(int64(2)))
|
|
||||||
|
|
||||||
res, err := client.GeoRadius("Sicily", 15, 37, &redis.GeoRadiusQuery{Radius: 200}).Result()
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(res).To(HaveLen(2))
|
Expect(res).To(HaveLen(2))
|
||||||
Expect(res[0].Name).To(Equal("Palermo"))
|
Expect(res[0].Name).To(Equal("Palermo"))
|
||||||
|
@ -2590,14 +2583,6 @@ var _ = Describe("Commands", func() {
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should search geo radius with options", func() {
|
It("should search geo radius with options", func() {
|
||||||
locations := []*redis.GeoLocation{
|
|
||||||
&redis.GeoLocation{Longitude: 13.361389, Latitude: 38.115556, Name: "Palermo"},
|
|
||||||
&redis.GeoLocation{Longitude: 15.087269, Latitude: 37.502669, Name: "Catania"},
|
|
||||||
}
|
|
||||||
geoAdd := client.GeoAdd("Sicily", locations...)
|
|
||||||
Expect(geoAdd.Err()).NotTo(HaveOccurred())
|
|
||||||
Expect(geoAdd.Val()).To(Equal(int64(2)))
|
|
||||||
|
|
||||||
res, err := client.GeoRadius("Sicily", 15, 37, &redis.GeoRadiusQuery{
|
res, err := client.GeoRadius("Sicily", 15, 37, &redis.GeoRadiusQuery{
|
||||||
Radius: 200,
|
Radius: 200,
|
||||||
Unit: "km",
|
Unit: "km",
|
||||||
|
@ -2610,27 +2595,41 @@ var _ = Describe("Commands", func() {
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(res).To(HaveLen(2))
|
Expect(res).To(HaveLen(2))
|
||||||
Expect(res[1].Name).To(Equal("Palermo"))
|
Expect(res[1].Name).To(Equal("Palermo"))
|
||||||
Expect(res[1].Distance).To(Equal(190.4424))
|
Expect(res[1].Dist).To(Equal(190.4424))
|
||||||
Expect(res[1].GeoHash).To(Equal(int64(3479099956230698)))
|
Expect(res[1].GeoHash).To(Equal(int64(3479099956230698)))
|
||||||
Expect(res[1].Longitude).To(Equal(13.361389338970184))
|
Expect(res[1].Longitude).To(Equal(13.361389338970184))
|
||||||
Expect(res[1].Latitude).To(Equal(38.115556395496299))
|
Expect(res[1].Latitude).To(Equal(38.115556395496299))
|
||||||
Expect(res[0].Name).To(Equal("Catania"))
|
Expect(res[0].Name).To(Equal("Catania"))
|
||||||
Expect(res[0].Distance).To(Equal(56.4413))
|
Expect(res[0].Dist).To(Equal(56.4413))
|
||||||
|
Expect(res[0].GeoHash).To(Equal(int64(3479447370796909)))
|
||||||
|
Expect(res[0].Longitude).To(Equal(15.087267458438873))
|
||||||
|
Expect(res[0].Latitude).To(Equal(37.50266842333162))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should search geo radius with WithDist=false", func() {
|
||||||
|
res, err := client.GeoRadius("Sicily", 15, 37, &redis.GeoRadiusQuery{
|
||||||
|
Radius: 200,
|
||||||
|
Unit: "km",
|
||||||
|
WithGeoHash: true,
|
||||||
|
WithCoord: true,
|
||||||
|
Count: 2,
|
||||||
|
Sort: "ASC",
|
||||||
|
}).Result()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(res).To(HaveLen(2))
|
||||||
|
Expect(res[1].Name).To(Equal("Palermo"))
|
||||||
|
Expect(res[1].Dist).To(Equal(float64(0)))
|
||||||
|
Expect(res[1].GeoHash).To(Equal(int64(3479099956230698)))
|
||||||
|
Expect(res[1].Longitude).To(Equal(13.361389338970184))
|
||||||
|
Expect(res[1].Latitude).To(Equal(38.115556395496299))
|
||||||
|
Expect(res[0].Name).To(Equal("Catania"))
|
||||||
|
Expect(res[0].Dist).To(Equal(float64(0)))
|
||||||
Expect(res[0].GeoHash).To(Equal(int64(3479447370796909)))
|
Expect(res[0].GeoHash).To(Equal(int64(3479447370796909)))
|
||||||
Expect(res[0].Longitude).To(Equal(15.087267458438873))
|
Expect(res[0].Longitude).To(Equal(15.087267458438873))
|
||||||
Expect(res[0].Latitude).To(Equal(37.50266842333162))
|
Expect(res[0].Latitude).To(Equal(37.50266842333162))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should search geo radius by member with options", func() {
|
It("should search geo radius by member with options", func() {
|
||||||
locations := []*redis.GeoLocation{
|
|
||||||
&redis.GeoLocation{Longitude: 13.361389, Latitude: 38.115556, Name: "Palermo"},
|
|
||||||
&redis.GeoLocation{Longitude: 15.087269, Latitude: 37.502669, Name: "Catania"},
|
|
||||||
}
|
|
||||||
|
|
||||||
geoAdd := client.GeoAdd("Sicily", locations...)
|
|
||||||
Expect(geoAdd.Err()).NotTo(HaveOccurred())
|
|
||||||
Expect(geoAdd.Val()).To(Equal(int64(2)))
|
|
||||||
|
|
||||||
res, err := client.GeoRadiusByMember("Sicily", "Catania", &redis.GeoRadiusQuery{
|
res, err := client.GeoRadiusByMember("Sicily", "Catania", &redis.GeoRadiusQuery{
|
||||||
Radius: 200,
|
Radius: 200,
|
||||||
Unit: "km",
|
Unit: "km",
|
||||||
|
@ -2643,25 +2642,18 @@ var _ = Describe("Commands", func() {
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(res).To(HaveLen(2))
|
Expect(res).To(HaveLen(2))
|
||||||
Expect(res[0].Name).To(Equal("Catania"))
|
Expect(res[0].Name).To(Equal("Catania"))
|
||||||
Expect(res[0].Distance).To(Equal(0.0))
|
Expect(res[0].Dist).To(Equal(0.0))
|
||||||
Expect(res[0].GeoHash).To(Equal(int64(3479447370796909)))
|
Expect(res[0].GeoHash).To(Equal(int64(3479447370796909)))
|
||||||
Expect(res[0].Longitude).To(Equal(15.087267458438873))
|
Expect(res[0].Longitude).To(Equal(15.087267458438873))
|
||||||
Expect(res[0].Latitude).To(Equal(37.50266842333162))
|
Expect(res[0].Latitude).To(Equal(37.50266842333162))
|
||||||
Expect(res[1].Name).To(Equal("Palermo"))
|
Expect(res[1].Name).To(Equal("Palermo"))
|
||||||
Expect(res[1].Distance).To(Equal(166.2742))
|
Expect(res[1].Dist).To(Equal(166.2742))
|
||||||
Expect(res[1].GeoHash).To(Equal(int64(3479099956230698)))
|
Expect(res[1].GeoHash).To(Equal(int64(3479099956230698)))
|
||||||
Expect(res[1].Longitude).To(Equal(13.361389338970184))
|
Expect(res[1].Longitude).To(Equal(13.361389338970184))
|
||||||
Expect(res[1].Latitude).To(Equal(38.115556395496299))
|
Expect(res[1].Latitude).To(Equal(38.115556395496299))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should search geo radius with no results", func() {
|
It("should search geo radius with no results", func() {
|
||||||
geoAdd := client.GeoAdd("Sicily", &redis.GeoLocation{
|
|
||||||
Longitude: 13.361389, Latitude: 38.115556, Name: "Palermo"},
|
|
||||||
&redis.GeoLocation{Longitude: 15.087269, Latitude: 37.502669, Name: "Catania"},
|
|
||||||
)
|
|
||||||
Expect(geoAdd.Err()).NotTo(HaveOccurred())
|
|
||||||
Expect(geoAdd.Val()).To(Equal(int64(2)))
|
|
||||||
|
|
||||||
res, err := client.GeoRadius("Sicily", 99, 37, &redis.GeoRadiusQuery{
|
res, err := client.GeoRadius("Sicily", 99, 37, &redis.GeoRadiusQuery{
|
||||||
Radius: 200,
|
Radius: 200,
|
||||||
Unit: "km",
|
Unit: "km",
|
||||||
|
@ -2682,15 +2674,6 @@ var _ = Describe("Commands", func() {
|
||||||
// "166274.15156960033"
|
// "166274.15156960033"
|
||||||
// GEODIST Sicily Palermo Catania km
|
// GEODIST Sicily Palermo Catania km
|
||||||
// "166.27415156960032"
|
// "166.27415156960032"
|
||||||
locations := []*redis.GeoLocation{
|
|
||||||
&redis.GeoLocation{Longitude: 13.361389, Latitude: 38.115556, Name: "Palermo"},
|
|
||||||
&redis.GeoLocation{Longitude: 15.087269, Latitude: 37.502669, Name: "Catania"},
|
|
||||||
}
|
|
||||||
|
|
||||||
geoAdd := client.GeoAdd("Sicily", locations...)
|
|
||||||
Expect(geoAdd.Err()).NotTo(HaveOccurred())
|
|
||||||
Expect(geoAdd.Val()).To(Equal(int64(2)))
|
|
||||||
|
|
||||||
geoDist := client.GeoDist("Sicily", "Palermo", "Catania", "km")
|
geoDist := client.GeoDist("Sicily", "Palermo", "Catania", "km")
|
||||||
Expect(geoDist.Err()).NotTo(HaveOccurred())
|
Expect(geoDist.Err()).NotTo(HaveOccurred())
|
||||||
Expect(geoDist.Val()).To(Equal(166.27415156960032))
|
Expect(geoDist.Val()).To(Equal(166.27415156960032))
|
||||||
|
@ -2701,20 +2684,11 @@ var _ = Describe("Commands", func() {
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should get geo hash in string representation", func() {
|
It("should get geo hash in string representation", func() {
|
||||||
locations := []*redis.GeoLocation{
|
|
||||||
&redis.GeoLocation{Longitude: 13.361389, Latitude: 38.115556, Name: "Palermo"},
|
|
||||||
&redis.GeoLocation{Longitude: 15.087269, Latitude: 37.502669, Name: "Catania"},
|
|
||||||
}
|
|
||||||
geoAdd := client.GeoAdd("Sicily", locations...)
|
|
||||||
Expect(geoAdd.Err()).NotTo(HaveOccurred())
|
|
||||||
Expect(geoAdd.Val()).To(Equal(int64(2)))
|
|
||||||
|
|
||||||
res, err := client.GeoHash("Sicily", "Palermo", "Catania").Result()
|
res, err := client.GeoHash("Sicily", "Palermo", "Catania").Result()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(res[0]).To(Equal("sqc8b49rny0"))
|
Expect(res[0]).To(Equal("sqc8b49rny0"))
|
||||||
Expect(res[1]).To(Equal("sqdtr74hyu0"))
|
Expect(res[1]).To(Equal("sqdtr74hyu0"))
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("marshaling/unmarshaling", func() {
|
Describe("marshaling/unmarshaling", func() {
|
||||||
|
|
22
parser.go
22
parser.go
|
@ -629,27 +629,28 @@ func clusterSlotInfoSliceParser(cn *conn, n int64) (interface{}, error) {
|
||||||
return infos, nil
|
return infos, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func geoLocationParser(cn *conn, n int64) (interface{}, error) {
|
func newGeoLocationParser(q *GeoRadiusQuery) multiBulkParser {
|
||||||
loc := &GeoLocation{}
|
return func(cn *conn, n int64) (interface{}, error) {
|
||||||
|
var loc GeoLocation
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
loc.Name, err = readStringReply(cn)
|
loc.Name, err = readStringReply(cn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if n >= 2 {
|
if q.WithDist {
|
||||||
loc.Distance, err = readFloatReply(cn)
|
loc.Dist, err = readFloatReply(cn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if n >= 3 {
|
if q.WithGeoHash {
|
||||||
loc.GeoHash, err = readIntReply(cn)
|
loc.GeoHash, err = readIntReply(cn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if n >= 4 {
|
if q.WithCoord {
|
||||||
n, err := readArrayHeader(cn)
|
n, err := readArrayHeader(cn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -668,13 +669,15 @@ func geoLocationParser(cn *conn, n int64) (interface{}, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return loc, nil
|
return &loc, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func geoLocationSliceParser(cn *conn, n int64) (interface{}, error) {
|
func newGeoLocationSliceParser(q *GeoRadiusQuery) multiBulkParser {
|
||||||
|
return func(cn *conn, n int64) (interface{}, error) {
|
||||||
locs := make([]GeoLocation, 0, n)
|
locs := make([]GeoLocation, 0, n)
|
||||||
for i := int64(0); i < n; i++ {
|
for i := int64(0); i < n; i++ {
|
||||||
v, err := readReply(cn, geoLocationParser)
|
v, err := readReply(cn, newGeoLocationParser(q))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -690,4 +693,5 @@ func geoLocationSliceParser(cn *conn, n int64) (interface{}, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return locs, nil
|
return locs, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue