go get -u github.com/umpc/go-fdbgeo
Package fdbgeo
contains tools for building geospatial layers using FoundationDB with Geohash-encoded keys.
This package uses its complimentary zrange
package, for performing geospatial range queries using FoundationDB with Geohash-encoded keys and a search radius.
The RadialRange
method appears to be sufficient for range queries of around 5,000km or less. Changes that efficiently add support for larger query ranges are welcome here.
Note: As of 5/26/2018, changes from apple/foundationdb
PR #408 must be applied to use this package, or a runtime panic will occur during subspace encoding.
...
rangeParams := fdbgeo.RadialRangeParams{
Subspace: dir,
Radius: 32.18688,
Latitude: 37.334722,
Longitude: -122.008889,
}
keyRanges := rangeParams.RadialRange()
fdbRangeOptions := fdb.RangeOptions{
Mode: fdb.StreamingModeWantAll,
}
ret, err := db.ReadTransact(func(tr fdb.ReadTransaction) (ret interface{}, e error) {
rangeResults := make([]fdb.RangeResult, len(keyRanges))
for i, keyRange := range keyRanges {
rangeResults[i] = tr.GetRange(keyRange, fdbRangeOptions)
}
var kvList []fdb.KeyValue
for _, rangeResult := range rangeResults {
ri := rangeResult.Iterator()
for ri.Advance() {
kv := ri.MustGet()
geohashID, err := fdbgeo.UnpackUint(kv.Key, -2)
if err != nil {
panic(err)
}
// Running WithinRadius before value parsing may benefit performance,
// though it depends on the data model in use.
if !rangeParams.WithinRadius(geohashID) {
continue
}
kvList = append(kvList, kv)
}
}
return kvList, e
})
...
Note: Geohash range searches are imprecise. Results should be filtered using the input radius where precision is desired.
- The
RadialRange
method was inspired by the algorithm in the "Search" section of this page.