Lucene.net邻近搜索

时间:2012-12-13 17:15:34

标签: geolocation lucene.net

是否有任何人有使用lucene.net索引纬度和经度值的经验,然后根据距离单点的距离返回一组有序的结果?

Lucene.Net.Spatial图书馆能帮助我吗?

1 个答案:

答案 0 :(得分:4)

派对有点晚了,但是,空间库是开始这个​​的地方。它背后的基础是:

1)在文档中添加Lat和Long字段

doc.Add(new Field("Latitude", 
                  NumericUtils.DoubleToPrefixCoded(Latitude), 
                  Field.Store.YES, Field.Index.NOT_ANALYZED));

doc.Add(new Field("Longitude", 
                  NumericUtils.DoubleToPrefixCoded(Longitude), 
                  Field.Store.YES, Field.Index.NOT_ANALYZED));

2)为您的搜索需要支持的每个粒度层创建绘图仪

IProjector projector = new SinusoidalProjector();
var ctp = new CartesianTierPlotter(0, projector, 
                                   Fields.LocationTierPrefix);
StartTier = ctp.BestFit(MaxKms);
EndTier = ctp.BestFit(MinKms);

Plotters = new Dictionary<int, CartesianTierPlotter>();
for (var tier = StartTier; tier <= EndTier; tier++)
{
    Plotters.Add(tier, new CartesianTierPlotter(tier, 
                                            projector, 
                                            Fields.LocationTierPrefix));
}

3)使用绘图仪为每个层级索引文档

private static void AddCartesianTiers(double latitude, 
                                      double longitude, 
                                      Document document)
{
    for (var tier = StartTier; tier <= EndTier; tier++)
    {
        var ctp = Plotters[tier];
        var boxId = ctp.GetTierBoxId(latitude, longitude);
        document.Add(new Field(ctp.GetTierFieldName(),
                        NumericUtils.DoubleToPrefixCoded(boxId),
                        Field.Store.YES,
                        Field.Index.NOT_ANALYZED_NO_NORMS));
    }
}

将文档编入索引后,您可以继续构建查询。此示例使用ConstantScoreQuery,但您可以将其替换为您的远程评分:

/*  Builder allows us to build a polygon which we will use to limit  
 * search scope on our cartesian tiers, this is like putting a grid 
 * over a map */
var builder = new CartesianPolyFilterBuilder(Fields.LocationTierPrefix);

/*  Bounding area draws the polygon, this can be thought of as working  
 * out which squares of the grid over a map to search */
var boundingArea = builder.GetBoundingArea(Latitude, 
                Longitude, 
                DistanceInKilometres * ProductSearchEngine.KmsToMiles);

/*  We refine, this is the equivalent of drawing a circle on the map,  
 *  within our grid squares, ignoring the parts the squares we are  
 *  searching that aren't within the circle - ignoring extraneous corners 
 *  and such */
var distFilter = new LatLongDistanceFilter(boundingArea, 
                                    DistanceInKilometres * KmsToMiles,
                                    Latitude, 
                                    Longitude, 
                                    ProductSearchEngine.Fields.Latitude,
                                    ProductSearchEngine.Fields.Longitude);

/*  We add a query stating we will only search against products that have 
 * GeoCode information */
var query = new TermQuery(new Term(Fields.HasGeoCode, 
                                   FieldFlags.HasField));

/*  Add our filter, this will stream through our results and 
 * determine eligibility */
masterQuery.Add(new ConstantScoreQuery(distanceFilter), 
                BooleanClause.Occur.MUST);

所有这些都来自我刚刚写的一篇博文,同时也看到了类似的问题。您可以在http://www.leapinggorilla.com/Blog/Read/1005/spatial-search-in-lucenenet

看到它