目前我们使用的是Lucene 4.0,上面对GEO query的使用是这样的,索引阶段使用geo hash索引多个级别的geo grid,检索阶段获取geo grid做termquery,or起来,最后search之后在collector中按照距离做一次手动的过滤,这样做不方便的是geo query不能任意和其他query做or组合。
又查看了lucene spatial中的实现,是直接确定精度之后做索引,索引可能较快了,但是检索阶段需要使用PrefixQuery,感觉上灵活性较差,需要遍历每个最小的grid(具体仍需测试和权衡),检索阶段Geo Query是FilteredQuery(MatchAllDocsQuery, GEOFilter),GEO filter实际上主要接口是getDocIdSet(所以solr中很多filter是要缓存的),这样geo query是可以和其他query任意组合的。
我也按照这个思路写了个geo filter,实测一下发现比之前的性能有很大提高。
代码读下来,之所以提高有两处:
1.Collector中acceptDocsOutOfOrder()返回false,这样从不同term query返回的dicid每次需要在堆中选择一下;
2.对应的Term Query做了打分操作(DisconjunctionSumScorer),但实际scorer其实是在collector中完成,这样就浪费了。
另外发现query有个rewrite方法,可以对查询做优化,对于连续的And操作,有Conjunction Query做优化。
使用FilteredQuery经rewrite之后变成ConstantScoreQuery,没什么overhead。