2012-12-13 160 views
5

有没有人拥有lucene.net index经纬度值的经验,然后根据距单点距离返回一组有序的结果?Lucene.net proximity搜索

Lucene.Net.Spatial库对我有所帮助吗?

+1

好问题。我也想知道。 –

回答

4

晚会有点晚,但是,空间图书馆是开始的地方。其背后的基础是:

1)添加纬度和长域到您的文档

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

+0

感谢您的好例子。我遇到了boundingArea部分的问题......只是提供的文档相互之间距离很近,但距离要求的坐标很远,所以LatLongDistanceFilter检查它们并发现它们'离得太远,所以没有结果返回。 – Jarvis

+1

我在我们的博客中添加了另一个工作示例(http://leapinggorilla.com/Blog/Read/1010/spatial-search-in-lucenenet---worked-example)。这有你需要看到一个演示应用程序运行的所有代码,所以应该有希望帮助你。 – Wolfwyrd