mirror of https://github.com/go-redis/redis.git
Merge pull request #176 from go-redis/feature/geo-more
Added binding for GEORADIUSBYMEMBER, GEODIST AND GEOHASH.
This commit is contained in:
commit
f04e7879e6
|
@ -779,14 +779,11 @@ type GeoLocation struct {
|
||||||
|
|
||||||
// GeoRadiusQuery is used with GeoRadius to query geospatial index.
|
// GeoRadiusQuery is used with GeoRadius to query geospatial index.
|
||||||
type GeoRadiusQuery struct {
|
type GeoRadiusQuery struct {
|
||||||
Key string
|
|
||||||
Longitude float64
|
|
||||||
Latitude float64
|
|
||||||
Radius float64
|
Radius float64
|
||||||
// Can be m, km, ft, or mi. Default is km.
|
// Can be m, km, ft, or mi. Default is km.
|
||||||
Unit string
|
Unit string
|
||||||
WithCoordinates bool
|
WithCoord bool
|
||||||
WithDistance bool
|
WithDist bool
|
||||||
WithGeoHash bool
|
WithGeoHash bool
|
||||||
Count int
|
Count int
|
||||||
// Can be ASC or DESC. Default is no sort order.
|
// Can be ASC or DESC. Default is no sort order.
|
||||||
|
|
49
commands.go
49
commands.go
|
@ -1688,22 +1688,17 @@ func (c *commandable) GeoAdd(key string, geoLocation ...*GeoLocation) *IntCmd {
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *commandable) GeoRadius(query *GeoRadiusQuery) *GeoLocationCmd {
|
func (c *commandable) geoRadius(args []interface{}, query *GeoRadiusQuery) *GeoLocationCmd {
|
||||||
args := make([]interface{}, 6)
|
args = append(args, query.Radius)
|
||||||
args[0] = "GEORADIUS"
|
|
||||||
args[1] = query.Key
|
|
||||||
args[2] = query.Longitude
|
|
||||||
args[3] = query.Latitude
|
|
||||||
args[4] = query.Radius
|
|
||||||
if query.Unit != "" {
|
if query.Unit != "" {
|
||||||
args[5] = query.Unit
|
args = append(args, query.Unit)
|
||||||
} else {
|
} else {
|
||||||
args[5] = "km"
|
args = append(args, "km")
|
||||||
}
|
}
|
||||||
if query.WithCoordinates {
|
if query.WithCoord {
|
||||||
args = append(args, "WITHCOORD")
|
args = append(args, "WITHCOORD")
|
||||||
}
|
}
|
||||||
if query.WithDistance {
|
if query.WithDist {
|
||||||
args = append(args, "WITHDIST")
|
args = append(args, "WITHDIST")
|
||||||
}
|
}
|
||||||
if query.WithGeoHash {
|
if query.WithGeoHash {
|
||||||
|
@ -1715,8 +1710,38 @@ func (c *commandable) GeoRadius(query *GeoRadiusQuery) *GeoLocationCmd {
|
||||||
if query.Sort != "" {
|
if query.Sort != "" {
|
||||||
args = append(args, query.Sort)
|
args = append(args, query.Sort)
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := NewGeoLocationCmd(args...)
|
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 {
|
||||||
|
args := []interface{}{"GEORADIUSBYMEMBER", key, member}
|
||||||
|
return c.geoRadius(args, query)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *commandable) GeoDist(key string, member1, member2, unit string) *FloatCmd {
|
||||||
|
if unit == "" {
|
||||||
|
unit = "km"
|
||||||
|
}
|
||||||
|
cmd := NewFloatCmd("GEODIST", key, member1, member2, unit)
|
||||||
|
c.Process(cmd)
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *commandable) GeoHash(key string, members ...string) *StringSliceCmd {
|
||||||
|
args := make([]interface{}, 2+len(members))
|
||||||
|
args[0] = "GEOHASH"
|
||||||
|
args[1] = key
|
||||||
|
for i, member := range members {
|
||||||
|
args[2+i] = member
|
||||||
|
}
|
||||||
|
cmd := NewStringSliceCmd(args...)
|
||||||
|
c.Process(cmd)
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
161
commands_test.go
161
commands_test.go
|
@ -2532,63 +2532,168 @@ var _ = Describe("Commands", func() {
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("Geo add and radius search", func() {
|
Describe("Geo add and radius search", func() {
|
||||||
|
|
||||||
It("should add one geo location", func() {
|
It("should add one geo location", func() {
|
||||||
geoAdd := client.GeoAdd("Sicily", &redis.GeoLocation{Longitude: 13.361389, Latitude: 38.115556, Name: "Palermo"})
|
geoAdd := client.GeoAdd(
|
||||||
|
"Sicily",
|
||||||
|
&redis.GeoLocation{Longitude: 13.361389, Latitude: 38.115556, Name: "Palermo"},
|
||||||
|
)
|
||||||
Expect(geoAdd.Err()).NotTo(HaveOccurred())
|
Expect(geoAdd.Err()).NotTo(HaveOccurred())
|
||||||
Expect(geoAdd.Val()).To(Equal(int64(1)))
|
Expect(geoAdd.Val()).To(Equal(int64(1)))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should add multiple geo locations", func() {
|
It("should add multiple geo locations", func() {
|
||||||
geoAdd := client.GeoAdd("Sicily", &redis.GeoLocation{Longitude: 13.361389, Latitude: 38.115556, Name: "Palermo"},
|
geoAdd := client.GeoAdd(
|
||||||
&redis.GeoLocation{Longitude: 15.087269, Latitude: 37.502669, Name: "Catania"})
|
"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.Err()).NotTo(HaveOccurred())
|
||||||
Expect(geoAdd.Val()).To(Equal(int64(2)))
|
Expect(geoAdd.Val()).To(Equal(int64(2)))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should search geo radius", func() {
|
It("should search geo radius", func() {
|
||||||
geoAdd := client.GeoAdd("Sicily", &redis.GeoLocation{Longitude: 13.361389, Latitude: 38.115556, Name: "Palermo"},
|
geoAdd := client.GeoAdd(
|
||||||
&redis.GeoLocation{Longitude: 15.087269, Latitude: 37.502669, Name: "Catania"})
|
"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.Err()).NotTo(HaveOccurred())
|
||||||
Expect(geoAdd.Val()).To(Equal(int64(2)))
|
Expect(geoAdd.Val()).To(Equal(int64(2)))
|
||||||
|
|
||||||
geoRadius := client.GeoRadius(&redis.GeoRadiusQuery{Key: "Sicily", Longitude: 15, Latitude: 37, Radius: 200})
|
res, err := client.GeoRadius("Sicily", 15, 37, &redis.GeoRadiusQuery{Radius: 200}).Result()
|
||||||
Expect(geoRadius.Err()).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(geoRadius.Val()[0].Name).To(Equal("Palermo"))
|
Expect(res).To(HaveLen(2))
|
||||||
Expect(geoRadius.Val()[1].Name).To(Equal("Catania"))
|
Expect(res[0].Name).To(Equal("Palermo"))
|
||||||
|
Expect(res[1].Name).To(Equal("Catania"))
|
||||||
})
|
})
|
||||||
|
|
||||||
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"},
|
locations := []*redis.GeoLocation{
|
||||||
&redis.GeoLocation{Longitude: 15.087269, Latitude: 37.502669, Name: "Catania"}}
|
&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{
|
||||||
|
Radius: 200,
|
||||||
|
Unit: "km",
|
||||||
|
WithGeoHash: true,
|
||||||
|
WithCoord: true,
|
||||||
|
WithDist: 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].Distance).To(Equal(190.4424))
|
||||||
|
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].Distance).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 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...)
|
geoAdd := client.GeoAdd("Sicily", locations...)
|
||||||
Expect(geoAdd.Err()).NotTo(HaveOccurred())
|
Expect(geoAdd.Err()).NotTo(HaveOccurred())
|
||||||
Expect(geoAdd.Val()).To(Equal(int64(2)))
|
Expect(geoAdd.Val()).To(Equal(int64(2)))
|
||||||
|
|
||||||
geoRadius := client.GeoRadius(&redis.GeoRadiusQuery{Key: "Sicily", Longitude: 15, Latitude: 37, Radius: 200, Unit: "km", WithGeoHash: true, WithCoordinates: true, WithDistance: true, Count: 2, Sort: "ASC"})
|
res, err := client.GeoRadiusByMember("Sicily", "Catania", &redis.GeoRadiusQuery{
|
||||||
Expect(geoRadius.Err()).NotTo(HaveOccurred())
|
Radius: 200,
|
||||||
Expect(geoRadius.Val()[1].Name).To(Equal("Palermo"))
|
Unit: "km",
|
||||||
Expect(geoRadius.Val()[1].Distance).To(Equal(190.4424))
|
WithGeoHash: true,
|
||||||
Expect(geoRadius.Val()[1].GeoHash).To(Equal(int64(3479099956230698)))
|
WithCoord: true,
|
||||||
Expect(geoRadius.Val()[1].Longitude).To(Equal(13.361389338970184))
|
WithDist: true,
|
||||||
Expect(geoRadius.Val()[1].Latitude).To(Equal(38.115556395496299))
|
Count: 2,
|
||||||
Expect(geoRadius.Val()[0].Name).To(Equal("Catania"))
|
Sort: "ASC",
|
||||||
Expect(geoRadius.Val()[0].Distance).To(Equal(56.4413))
|
}).Result()
|
||||||
Expect(geoRadius.Val()[0].GeoHash).To(Equal(int64(3479447370796909)))
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(geoRadius.Val()[0].Longitude).To(Equal(15.087267458438873))
|
Expect(res).To(HaveLen(2))
|
||||||
Expect(geoRadius.Val()[0].Latitude).To(Equal(37.50266842333162))
|
Expect(res[0].Name).To(Equal("Catania"))
|
||||||
|
Expect(res[0].Distance).To(Equal(0.0))
|
||||||
|
Expect(res[0].GeoHash).To(Equal(int64(3479447370796909)))
|
||||||
|
Expect(res[0].Longitude).To(Equal(15.087267458438873))
|
||||||
|
Expect(res[0].Latitude).To(Equal(37.50266842333162))
|
||||||
|
Expect(res[1].Name).To(Equal("Palermo"))
|
||||||
|
Expect(res[1].Distance).To(Equal(166.2742))
|
||||||
|
Expect(res[1].GeoHash).To(Equal(int64(3479099956230698)))
|
||||||
|
Expect(res[1].Longitude).To(Equal(13.361389338970184))
|
||||||
|
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"},
|
geoAdd := client.GeoAdd("Sicily", &redis.GeoLocation{
|
||||||
&redis.GeoLocation{Longitude: 15.087269, Latitude: 37.502669, Name: "Catania"})
|
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.Err()).NotTo(HaveOccurred())
|
||||||
Expect(geoAdd.Val()).To(Equal(int64(2)))
|
Expect(geoAdd.Val()).To(Equal(int64(2)))
|
||||||
|
|
||||||
geoRadius := client.GeoRadius(&redis.GeoRadiusQuery{Key: "Sicily", Longitude: 99, Latitude: 37, Radius: 200, Unit: "km", WithGeoHash: true, WithCoordinates: true, WithDistance: true})
|
res, err := client.GeoRadius("Sicily", 99, 37, &redis.GeoRadiusQuery{
|
||||||
Expect(geoRadius.Err()).NotTo(HaveOccurred())
|
Radius: 200,
|
||||||
Expect(len(geoRadius.Val())).To(Equal(0))
|
Unit: "km",
|
||||||
|
WithGeoHash: true,
|
||||||
|
WithCoord: true,
|
||||||
|
WithDist: true,
|
||||||
|
}).Result()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(res).To(HaveLen(0))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("should get geo distance with unit options", func() {
|
||||||
|
// From Redis CLI, note the difference in rounding in m vs
|
||||||
|
// km on Redis itself.
|
||||||
|
//
|
||||||
|
// GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
|
||||||
|
// GEODIST Sicily Palermo Catania m
|
||||||
|
// "166274.15156960033"
|
||||||
|
// GEODIST Sicily Palermo Catania km
|
||||||
|
// "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")
|
||||||
|
Expect(geoDist.Err()).NotTo(HaveOccurred())
|
||||||
|
Expect(geoDist.Val()).To(Equal(166.27415156960032))
|
||||||
|
|
||||||
|
geoDist = client.GeoDist("Sicily", "Palermo", "Catania", "m")
|
||||||
|
Expect(geoDist.Err()).NotTo(HaveOccurred())
|
||||||
|
Expect(geoDist.Val()).To(Equal(166274.15156960033))
|
||||||
|
})
|
||||||
|
|
||||||
|
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()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(res[0]).To(Equal("sqc8b49rny0"))
|
||||||
|
Expect(res[1]).To(Equal("sqdtr74hyu0"))
|
||||||
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("marshaling/unmarshaling", func() {
|
Describe("marshaling/unmarshaling", func() {
|
||||||
|
|
Loading…
Reference in New Issue