Sphinx 的 SetGeoAnchor方法,
coreseek提供的中文翻译手册:
function SetGeoAnchor ( $attrlat, $attrlong, $lat, $long )
为地表距离计算设置锚点,并且允许使用它们。$attrlat 和$attrlong 是字符串,分别指定了对应经度和纬度的属性名称。$lat 和$long 是浮点值,
指定了锚点的经度和纬度值,以角度为单位。一旦设置了锚点,您就可以在您的过滤器和/或排序表达式中使用@geodist 特殊属性。Sphinx 将在每一次全文检索中计算给定经纬度与锚点之前的地表距离,并把此距离附加到匹配结果
上去。SetGeoAnchor 和索引属性数据中的经纬度值都是角度。而结果会以米为单位返回,因此地表距离 1000.0 代表 1 千米。一英里大约是 1609.344 米。
以下是Sphinx官网原文:
Prototype: function SetGeoAnchor ( $attrlat, $attrlong, $lat, $long )
Sets anchor point for and geosphere distance (geodistance) calculations, and enable them.
$attrlat and $attrlong must be strings that contain the names of latitude and longitude attributes, respectively. $lat and $long are floats that specify anchor point latitude and longitude, in radians.
Once an anchor point is set, you can use magic "@geodist" attribute name in your filters and/or sorting expressions. Sphinx will compute geosphere distance between the given anchor point and a point specified by latitude and lognitude attributes from each full-text match, and attach this value to the resulting match. The latitude and longitude values both in SetGeoAnchor and the index attribute data are expected to be in radians. The result will be returned in meters, so geodistance value of 1000.0 means 1 km. 1 mile is approximately 1609.344 meters.
coreseek这部分翻译有个问题,原文说的是弧度,而coreseek翻译成了角度,这是个错误。
一般由GPS提供的经纬度格式(角度)如:longitude:111.177579, latitude:53.051679 ,转换成弧度,公式为 (角度*Pi)/180,
首先在做索引的时候 ,得将经纬度数据源转换成弧度。
SQL数据源,如下转换:
SQL代码
- select id, radians(longitude) as longitude, radians(latitude) as latitude from locations
如果使用coreseek 提供的Python数据源,如下转换,math.radians:
Python代码
-
-
- import os, pymongo, math
- class MainSource(object):
- def __init__(self, conf):
- self.conf = conf
- self.idx = 0
- self.data = []
-
- def GetScheme(self):
- return [
- ('_id', {'docid':True, }),
- ('name', {'type':'text'}),
- ('address', {'type':'text'}),
- ('created_at', {'type':'integer'}),
- ('updated_at', {'type':'integer'}),
- ('deleted_at', {'type':'integer'}),
- ('longitude', {'type':'float'}),
- ('latitude', {'type':'float'}),
- ]
-
- def GetFieldOrder(self):
- return [('name', 'address')]
-
- def Connected(self):
- conn = pymongo.Connection(self.conf['dbhost'], int(self.conf['dbport']))
- db = conn[self.conf['dbname']]
- collection = db[self.conf['collection']]
- cur = collection.find()
- self.data = [ row for row in cur ]
- pass
-
- def NextDocument(self):
- if self.idx < len(self.data):
- item = self.data[self.idx]
- self._id = int(item["_id"])
- self.name = item["name"].encode('utf-8')
- if item.has_key('coordinates'):
- self.longitude = math.radians(item["coordinates"]["longitude"])
- self.latitude = math.radians(item["coordinates"]["latitude"])
- if item.has_key('address'):
- self.address = item["address"].encode('utf-8')
- if item.has_key('created_at'):
- self.created_at = item['created_at']
- if item.has_key('updated_at'):
- self.updated_at = item['updated_at']
- if item.has_key('deleted_at'):
- self.deleted_at = item['deleted_at']
- self.idx += 1
- return True
- else:
- return False
-
- if __name__ == '__main__':
- conf = {}
- source = MainSource(conf)
- source.Connected()
- while source.NextDocument():
- pass
PHP搜索代码示例:
PHP代码
- $long = (float)$_GET['longitude'];
- $lat = (float)$_GET['latitude'];
- $radius = (float) 10000.0 * 1.61;
-
- $cl = new SphinxClient();
- $cl->SetServer("localhost", 3312);
- $cl->SetMatchMode(SPH_MATCH_ANY);
- $cl->SetArrayResult(true);
- $cl->SetLimits(0, 100);
- $cl->SetGeoAnchor('latitude', 'longitude', (float) deg2rad($long), (float) deg2rad($lat));
-
- $cl->SetSortMode(SPH_SORT_EXTENDED, '@geodist asc');
- $cl->SetFilterFloatRange('@geodist', 0.0, $radius);
-
- $result = $cl->Query('', '*');