pink c
pink c

Reputation: 31

Lucene.Net 3.0.3 Spatial search

I am a newcomer to Lucene.Net. I started trying to use spatial searches with Lucene.Net 3.0.3 release.

Could someone have a simple demo project that can help me to understand how it works? Thank you, that would be very appreciated.

Upvotes: 3

Views: 1652

Answers (2)

David Kirkland
David Kirkland

Reputation: 2461

Just got spatial search working today. Below is the core SearchByLocation method:

public IList<SearchItem> SearchByLocation(string queryString, double longitude, double latitude, double searchRadiusKm, int maxHits = 10)
{
    IList<SearchItem> results;

    using (var searcher = new IndexSearcher(Directory, true))
    using (var analyser = new StandardAnalyzer(LuceneVersion))
    {
        var distance = DistanceUtils.Dist2Degrees(searchRadiusKm, DistanceUtils.EARTH_MEAN_RADIUS_KM);
        var searchArea = _spatialContext.MakeCircle(longitude, latitude, distance);

        var fields = new[] {Name};
        var parser = new MultiFieldQueryParser(LuceneVersion, fields, analyser);
        parser.DefaultOperator = QueryParser.Operator.OR; // Allow multiple terms.
        var query = ParseQuery(queryString, parser);

        var spatialArgs = new SpatialArgs(SpatialOperation.Intersects, searchArea);
        var spatialQuery = _strategy.MakeQuery(spatialArgs);
        var valueSource = _strategy.MakeRecipDistanceValueSource(searchArea);
        var valueSourceFilter = new ValueSourceFilter(new QueryWrapperFilter(spatialQuery), valueSource, 0, 1);

        var filteredSpatial = new FilteredQuery(query, valueSourceFilter);
        var spatialRankingQuery = new FunctionQuery(valueSource);

        var bq = new BooleanQuery();
        bq.Add(filteredSpatial,Occur.MUST);
        bq.Add(spatialRankingQuery,Occur.MUST);

        var hits = searcher.Search(bq, maxHits).ScoreDocs;

        results = MapResultsToSearchItems(hits, searcher);
    }

    return results;
}

The basic example works with Lucene.NET 3.0.3 and consists of 3 classes plus a test (example use) class. I don't think it makes sense to post the whole solution here.

The key part which drives the spatial search is this:

var spatialArgs = new SpatialArgs(SpatialOperation.Intersects, searchArea);
var spatialQuery = _strategy.MakeQuery(spatialArgs);
var valueSource = _strategy.MakeRecipDistanceValueSource(searchArea);
var valueSourceFilter = new ValueSourceFilter(new QueryWrapperFilter(spatialQuery), valueSource, 0, 1);

var filteredSpatial = new FilteredQuery(query, valueSourceFilter);
var spatialRankingQuery = new FunctionQuery(valueSource);

var bq = new BooleanQuery();
bq.Add(filteredSpatial,Occur.MUST);
bq.Add(spatialRankingQuery,Occur.MUST);

You can get the entire solution (VS2015) on GitHub.

Let me know if you have any questions and I'll try to help or improve the answer.

Upvotes: 3

Mark Broadhurst
Mark Broadhurst

Reputation: 2695

I've posted a Gist up this morning. https://gist.github.com/Mark-Broadhurst/8931898

It should get you going. Please note that it does not sort by distance yet (still working on that).

Upvotes: 2

Related Questions