5

有没有人有 lucene.net 索引纬度和经度值的经验,然后根据与单点的距离返回一组有序的结果?

Lucene.Net.Spatial 库会帮我解决这个问题吗?

4

1 回答 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看到它

于 2013-01-28T13:43:48.967 回答