3
votes

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.

2
Have you looked at the Java examples? Lucene.NET 3.0.3 and Lucene (Java) 3.0.3 have API symmetry, meaning the classes/methods etc. are named the same. Also, check out the contrib project for Lucene.NET which includes Spacial Search features.Bart Czernicki
Thank you for your information.pink c
Thank you for your information. But they seem not the same. I've downloaded the SRC of the Lucene.Net 3.0.3 Contrib Spatial. I try to figure out how it works and implement a project. But I got some problems, like I can not find some class such as: CartesianTierPlotter.pink c
It looks like you maybe correct, they are not the same..most of the classes are there but the Contrib is not up to parity with the Java version. What are you trying to do?...have you looked at alternatives i.e. SharpMap or using Spacial Indexes in SQL Server?Bart Czernicki
I have lots of data with the lat/lng points. And I come out an idea to try spatial search, like the distance between two places, finding the resault within 1 km. I used spatial indexes in SQL Server before with this idea. And I just wanna try the different kind of tools, like Lucene.Net Spatial, to do the same thing. Thank you.pink c

2 Answers

3
votes

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.

2
votes

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).