使用Lucene进行基于位置的搜索的SpatialQuery

时间:2009-06-27 03:56:58

标签: lucene lucene.net

我的lucene索引的纬度和经度字段索引如下:

doc.Add(new Field("latitude", latitude.ToString() , Field.Store.YES, Field.Index.UN_TOKENIZED));

doc.Add(new Field("longitude", longitude.ToString(), Field.Store.YES, Field.Index.UN_TOKENIZED));

我想从这个索引中检索一组文档,其lat和long值在给定范围内。

如您所知,Lat和long可能是负值。如何在Lucene中正确存储带符号的十进制数? 下面提到的方法是否会给出正确的结果,还是有其他方法可以做到这一点?

 Term lowerLatitude = new Term("latitude", bounds.South.ToString() );
                Term upperLatitude = new Term("latitude", bounds.North.ToString());
                RangeQuery latitudeRangeQuery = new RangeQuery(lowerLatitude, upperLatitude, true);
                findLocationQuery.Add(latitudeRangeQuery, BooleanClause.Occur.SHOULD);



                Term lowerLongitude = new Term("longitude", bounds.West.ToString());
                Term upperLongitude = new Term("longitude", bounds.East.ToString());
                RangeQuery longitudeRangeQuery = new RangeQuery(lowerLongitude, upperLongitude, true);
                findLocationQuery.Add(longitudeRangeQuery, BooleanClause.Occur.SHOULD);

另外,我想知道Lucene的ConstantScoreRangeQuery如何比RangeQuery类更好。

在此背景下面临另一个问题: 我在以下3个城市的索引中有一个文件:

  • Lyons,IL

    Oak Brook,IL

    加利福尼亚州旧金山

如果我输入“Lyons,IL”,则会出现此记录。 但如果我把旧金山,加州作为输入,那么它就不会。

但是,如果我按如下方式存储此文档的城市:

  • 旧金山,加利福尼亚州

    Lyons,IL

    Oak Brook,IL

    当我将旧金山,CA作为输入时,此记录会显示在搜索结果中。

我想要的是,如果我在输入中键入3个城市中的任何一个,我应该在搜索结果中获取此文档。

请帮助我实现这一目标。

感谢。

3 个答案:

答案 0 :(得分:3)

根据skaffman的建议,您可以使用所有热门地图应用使用的相同tile coordinate system。根据您的需要选择任何缩放级别,并且不要忘记使用前导零填充。

关于RangeQuery,它比ConstantScoreRangeQuery慢,并且限制了值的范围。

关于城邦问题,我们只能推测。但首先要检查的是索引条款和解析后的查询是你期望的。

答案 1 :(得分:1)

我认为最好的方法是按照上一篇文章的建议转换/标准化坐标。这个article就是这样做的。它实际上是非常好的面向对象的代码。

关于你的第二个问题。我会假设你有某种分析器问题。您使用相同的Analyzer进行索引和查询吗?你使用哪些标记器?

我建议使用Luke检查生成的索引,以查看实际可搜索的令牌。

- 哈迪

答案 2 :(得分:0)

此处的一个选项是将坐标转换为没有负数的系统。例如,我对英国的谷歌地图webapp有类似的问题,我将Lucene的UK Easting / Northings(范围从0到7位)字段与lat / long值一起存储。通过用左填充的零格式化这些东/北,我可以进行lucene范围查询。

美国是否有类似的坐标系?