空间索引的相关案例

package com.dianping.poi.dedup.util;


/**
 * Created with IntelliJ IDEA.
 * User: liwentao
 * Date: 14-6-13
 * Time: AM11:01
 * To change this template use File | Settings | File Templates.
 */
import java.io.File;
import java.io.IOException;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.document.IntField;
import org.apache.lucene.document.StoredField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.spatial.SpatialStrategy;
import org.apache.lucene.spatial.prefix.RecursivePrefixTreeStrategy;
import org.apache.lucene.spatial.prefix.tree.GeohashPrefixTree;
import org.apache.lucene.spatial.prefix.tree.SpatialPrefixTree;
import org.apache.lucene.spatial.query.SpatialArgs;
import org.apache.lucene.spatial.query.SpatialOperation;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.SimpleFSDirectory;
import org.apache.lucene.util.Version;


import com.spatial4j.core.context.SpatialContext;
import com.spatial4j.core.distance.DistanceUtils;
import com.spatial4j.core.shape.Point;
import com.spatial4j.core.shape.Shape;




public class SpatialSearch {


    private IndexWriter indexWriter;
    private IndexReader indexReader;
    private IndexSearcher searcher;
    private SpatialContext spatialContext;
    private SpatialStrategy spatialStrategy;


    public SpatialSearch(String indexPath) {


        StandardAnalyzer a = new StandardAnalyzer(Version.LUCENE_47);
        IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_47, a);
        Directory directory;


        try {
            directory = new SimpleFSDirectory(new File(indexPath));
            indexWriter = new IndexWriter(directory, iwc);
        } catch (IOException e) {
            e.printStackTrace();
        }


        this.spatialContext = SpatialContext.GEO;


        SpatialPrefixTree grid = new GeohashPrefixTree(spatialContext, 11);
        this.spatialStrategy = new RecursivePrefixTreeStrategy(grid, "location");
    }


    public void indexDocuments() throws IOException {


        indexWriter.addDocument(newGeoDocument(1, "Bangalore", spatialContext.makePoint(12.9558, 77.620979)));
        indexWriter.addDocument(newGeoDocument(2, "Cubbon Park", spatialContext.makePoint(12.974045, 77.591995)));
        indexWriter.addDocument(newGeoDocument(3, "Tipu palace", spatialContext.makePoint(12.959365, 77.573792)));
        indexWriter.addDocument(newGeoDocument(4, "Bangalore palace", spatialContext.makePoint(12.998095, 77.592041)));
        indexWriter.addDocument(newGeoDocument(5, "Monkey Bar", spatialContext.makePoint(12.97018, 77.61219)));
        indexWriter.addDocument(newGeoDocument(6, "Cafe Cofee day", spatialContext.makePoint(12.992189, 80.2348618)));


        indexWriter.commit();
        indexWriter.close();
    }




    private Document newGeoDocument(int id, String name, Shape shape) {


        FieldType ft = new FieldType();
        ft.setIndexed(true);
        ft.setStored(true);


        Document doc = new Document();


        doc.add(new IntField("id", id, Store.YES));
        doc.add(new Field("name", name, ft));
        for(IndexableField f: spatialStrategy.createIndexableFields(shape)) {
            doc.add(f);
        }


        doc.add(new StoredField(spatialStrategy.getFieldName(), spatialContext.toString(shape)));


        return doc;
    }


    public void setSearchIndexPath(String indexPath) throws IOException{
        this.indexReader = DirectoryReader.open(new SimpleFSDirectory(new File(indexPath)));
        this.searcher = new IndexSearcher(indexReader);
    }


    public void search(Double lat, Double lng, int distance) throws IOException{


        Point p = spatialContext.makePoint(lat, lng);
        SpatialArgs args = new SpatialArgs(SpatialOperation.Intersects,
                spatialContext.makeCircle(lat, lng, DistanceUtils.dist2Degrees(distance, DistanceUtils.EARTH_MEAN_RADIUS_KM)));
        Filter filter = spatialStrategy.makeFilter(args);


        ValueSource valueSource = spatialStrategy.makeDistanceValueSource(p);
        Sort distSort = new Sort(valueSource.getSortField(false)).rewrite(searcher);


        int limit = 10;
        TopDocs topDocs = searcher.search(new MatchAllDocsQuery(), filter, limit, distSort);
        ScoreDoc[] scoreDocs = topDocs.scoreDocs;


        for(ScoreDoc s: scoreDocs) {


            Document doc = searcher.doc(s.doc);
            Point docPoint = (Point) spatialContext.readShape(doc.get(spatialStrategy.getFieldName()));
            double docDistDEG = spatialContext.getDistCalc().distance(args.getShape().getCenter(), docPoint);
            double docDistInKM = DistanceUtils.degrees2Dist(docDistDEG, DistanceUtils.EARTH_EQUATORIAL_RADIUS_KM);
            System.out.println(doc.get("id") + "\t" + doc.get("name") + "\t" + docDistInKM + " km ");


        }
    }


    /**
     * @param args
     * @throws IOException
     */
    public static void main(String[] args) throws IOException {
        String indexPath = "luceneIndex4Test";


        SpatialSearch s = new SpatialSearch(indexPath);


        //Indexes sample documents
        s.indexDocuments();
        s.setSearchIndexPath(indexPath);


        //Get Places Within 4 kilometers from cubbon park.
        s.search(12.974045,77.591995, 4);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值