Damian
Damian

Reputation: 3050

How to use Lucene 4.0 Spatial API?

I cannot find any complete examples of how to use this API. The code below is not giving any results. Any idea why?

static String spatialPrefix = "_point";
static String latField = spatialPrefix + "lat";
static String lngField = spatialPrefix + "lon";

public static void main(String[] args) throws IOException {
    SpatialLuceneExample spatial = new SpatialLuceneExample();
    spatial.addData();
    IndexReader reader = DirectoryReader.open(modules.getDirectory());
    IndexSearcher searcher = new IndexSearcher(reader);
    searchAndUpdateDocument(38.9510000, -77.4107000, 100.0, searcher,
            modules);
}

private void addLocation(IndexWriter writer, String name, double lat,
        double lng) throws IOException {

    Document doc = new Document();

    doc.add(new org.apache.lucene.document.TextField("name", name,
            Field.Store.YES));
    doc.add(new org.apache.lucene.document.DoubleField(latField, lat,
            Field.Store.YES));
    doc.add(new org.apache.lucene.document.DoubleField(lngField, lng,
            Field.Store.YES));
    doc.add(new org.apache.lucene.document.TextField("metafile", "doc",
            Field.Store.YES));
    writer.addDocument(doc);
    System.out.println("===== Added Doc to index ====");
}

private void addData() throws IOException {
    IndexWriter writer = modules.getWriter();
    addLocation(writer, "McCormick & Schmick's Seafood Restaurant",
            38.9579000, -77.3572000);
    addLocation(writer, "Jimmy's Old Town Tavern", 38.9690000, -77.3862000);
    addLocation(writer, "Ned Devine's", 38.9510000, -77.4107000);
    addLocation(writer, "Old Brogue Irish Pub", 38.9955000, -77.2884000);
    //...
    writer.close();
}

private final static Logger logger = LogManager
        .getLogger(SpatialTools.class);

public static void searchAndUpdateDocument(double lo, double la,
        double dist, IndexSearcher searcher, LuceneModules modules) {
    SpatialContext ctx = SpatialContext.GEO;
    SpatialArgs args = new SpatialArgs(SpatialOperation.IsWithin,
            ctx.makeCircle(lo, la, DistanceUtils.dist2Degrees(dist,
                    DistanceUtils.EARTH_MEAN_RADIUS_KM)));

    PointVectorStrategy strategy = new PointVectorStrategy(ctx, "_point");
    // RecursivePrefixTreeStrategy recursivePrefixTreeStrategy = new
    // RecursivePrefixTreeStrategy(grid, fieldName);
            // How to use it?


            Query makeQueryDistanceScore = strategy.makeQueryDistanceScore(args);

    LuceneSearcher instance = LuceneSearcher.getInstance(modules);
    instance.getTopResults(makeQueryDistanceScore);
            //no results


    Filter geoFilter = strategy.makeFilter(args);

    try {
        Sort chainedSort = new Sort().rewrite(searcher);
        TopDocs docs = searcher.search(new MatchAllDocsQuery(), geoFilter,
                10000, chainedSort);
        logger.debug("search finished, num: " + docs.totalHits);
                    //no results
        for (ScoreDoc scoreDoc : docs.scoreDocs) {
            Document doc = searcher.doc(scoreDoc.doc);
            double la1 = Double.parseDouble(doc.get(latField));
            double lo1 = Double.parseDouble(doc.get(latField));
            double distDEG = ctx.getDistCalc().distance(
                    args.getShape().getCenter(), lo1, la1);

            logger.debug("dist deg: : " + distDEG);
            double distKM = DistanceUtils.degrees2Dist(distDEG,
                    DistanceUtils.EARTH_MEAN_RADIUS_KM);
            logger.debug("dist km: : " + distKM);
        }
    } catch (IOException e) {
        logger.error("fail to get the search result!", e);
    }
}

Upvotes: 3

Views: 8378

Answers (2)

David Smiley
David Smiley

Reputation: 4140

Did you see the javadocs? These docs in turn point to SpatialExample.java which is what you're looking for. What could I do to make them more obvious?

If you're bent on using a pair of doubles as the internal index approach then use PointVectorStrategy. However, you'll get superior filter performance if you instead use RecursivePrefixTreeStrategy. Presently, PVS does better distance sorting, though, scalability wise. You could use both for their respective benefits.

Just looking quickly at your example, I see you didn't use SpatialStrategy.createIndexableFields(). The intention is that you use that.

Upvotes: 8

vishnuc
vishnuc

Reputation: 11

See the following link for example : http://mad4search.blogspot.in/2013/06/implementing-geospatial-search-using.html

Upvotes: 1

Related Questions