2012-12-13 13 views
5

Hat jemand Erfahrung mit lucene.net Index Breite und Länge Werte dann eine geordnete Menge von Ergebnissen basierend auf Abstand von einem einzigen Punkt zurückgeben?Lucene.net Proximity-Suche

Wird die Lucene.Net.Spatial-Bibliothek mir dabei helfen?

+1

Gute Frage zu sehen. Ich würde auch gerne wissen. –

Antwort

4

Ein wenig spät auf die Party, aber ja, die Spatial Library ist der Ort, um damit zu beginnen. Die Grundlagen dahinter sind:

1) In Breite und Länge Felder in Ihrem Dokument

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) Plotter für die einzelnen Ebenen der Granularität erstellen, die Ihren Such

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)); 
} 
unterstützen muss

3) Verwenden Sie Ihren Plotter zu indizieren Dokument für jedes Tier

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)); 
    } 
} 

Mit Ihrer Dokument indiziert Sie können zum Erstellen einer Abfrage verschieben. Dieses Beispiel verwendet eine ConstantScoreQuery aber Sie können das für Ihre reichte Scoring auslagern:

/* 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); 

All dies aus einem Blog-Post genommen Ich schrieb, während bei einem ähnlichen Problem suchen. Sie können es bei http://www.leapinggorilla.com/Blog/Read/1005/spatial-search-in-lucenenet

+0

Danke für das tolle Beispiel. Ich habe ein Problem mit dem BoundingArea-Teil ... da stimmt etwas nicht, wo es nur Dokumente anbietet, die alle nahe beieinander liegen, aber weit weg von den Koordinaten, nach denen ich gefragt habe. Der LatLongDistanceFilter prüft sie und stellt fest, dass sie zu weit entfernt, so dass keine Ergebnisse zurückgegeben werden. – Jarvis

+1

Ich habe ein weiteres funktionierendes Beispiel zu unserem Blog hinzugefügt (http://leapinggorilla.com/Blog/Read/1010/spatial-search-in-lucenet----worked-example). Dies hat den ganzen Code, den Sie benötigen, um eine Demo-App zu sehen, die funktioniert, damit Sie hoffentlich weiterhelfen können. – Wolfwyrd