2012-12-13 3 views
5

누구나 lucene.net 색인 위도 및 경도 값을 가진 경험이 있습니까? 그렇다면 단일 지점으로부터의 거리를 기반으로 정렬 된 결과 집합을 반환합니까?Lucene.net 근접 검색

Lucene.Net.Spatial 라이브러리가 이것으로 전혀 도움이됩니까?

+1

좋은 질문입니다. 나는 또한 알고 싶다. –

답변

4

파티에 약간 늦었지만 예, Spatial 라이브러리가 여기부터 시작하는 곳입니다. 뒤에 기본 원리는 다음과 같다 :

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