2012-12-13 12 views
5

Qualcuno ha esperienza con i valori di latitudine e longitudine dell'indice di lucene.net, quindi restituisce un insieme ordinato di risultati in base alla distanza da un singolo punto?Lucene.net ricerca di prossimità

La libreria Lucene.Net.Spatial può aiutarmi affatto?

+1

Buona domanda. Mi piacerebbe anche sapere. –

risposta

4

Un po 'in ritardo per la festa, ma sì, la libreria Spaziale è il punto di partenza. Le basi dietro di esso sono:

1) Aggiungi campi Lat e lunghi al documento

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) Creare plotter per l'ogni livello di granularità che la ricerca deve supportare

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) Usa il tuo plotter per indicizzare il documento per ogni livello

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

Con il vostro documento indicizzato puoi passare alla costruzione di una query. Questo esempio utilizza un ConstantScoreQuery ma si può scambiare che fuori per il vostro punteggio a distanza:

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

Tutto questo è tratto da un post sul blog che ho appena scritto, mentre guardando un problema simile. Potete vederlo a http://www.leapinggorilla.com/Blog/Read/1005/spatial-search-in-lucenenet

+0

Grazie per l'ottimo esempio. Sto riscontrando un problema con la porzione boundingArea ... c'è qualcosa di sbagliato in cui si offrono solo documenti tutti vicini l'uno all'altro, ma lontani dalle coordinate che ho richiesto, quindi LatLongDistanceFilter li controlla e trova che sono " troppo lontano, quindi non vengono restituiti risultati. – Jarvis

+1

Ho aggiunto un altro esempio funzionante al nostro blog (http://leapinggorilla.com/Blog/Read/1010/spatial-search-in-lucenenet---worked-example). Questo ha tutto il codice che ti serve per vedere un'app demo funzionante, quindi spero che possa aiutarti. – Wolfwyrd