lucene 对地理位置的搜索

package com.lucenetest;

import java.io.IOException;
import java.text.ParseException;

import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
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.SortField;
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.RAMDirectory;
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 NewLocation {
	private SpatialContext ctx;
	private SpatialStrategy strategy;

	private Directory directory;

	protected void init() {
		this.ctx = SpatialContext.GEO;
		int maxLevels = 11;
		SpatialPrefixTree grid = new GeohashPrefixTree(ctx, maxLevels);
		this.strategy = new RecursivePrefixTreeStrategy(grid, "myGeoField");
		this.directory = new RAMDirectory();
	}
	
	protected void indexPoints() throws IOException, ParseException {
		IndexWriterConfig iwConfig = new IndexWriterConfig(Version.LUCENE_4_9,null);
		IndexWriter indexWriter = new IndexWriter(directory, iwConfig);
		
		indexWriter.addDocument(newSampleDocument( 2, ctx.makePoint(-80.93, 33.77)));
		indexWriter.addDocument(newSampleDocument( 4, ctx.readShapeFromWkt("POINT(60.9289094 -50.7693246)")));
		indexWriter.addDocument(newSampleDocument( 20, ctx.makePoint(0.1,0.1), ctx.makePoint(0, 0)));
		
		indexWriter.close();
	}
	
	private Document newSampleDocument(int id, Shape... shapes) {
		Document doc = new Document();
		doc.add(new IntField("id", id, Field.Store.YES));
		for (Shape shape : shapes) {
			for (IndexableField f : strategy.createIndexableFields(shape)) {
				doc.add(f);
			}
			Point pt = (Point) shape;
			doc.add(new StoredField(strategy.getFieldName(), pt.getX()+" "+pt.getY()));
		}
		return doc;
	}
	
	protected void search() throws Exception {
		IndexReader indexReader = DirectoryReader.open(directory);
		IndexSearcher indexSearcher = new IndexSearcher(indexReader);
		Sort idSort = new Sort(new SortField("id", SortField.Type.INT));
		
		{
			SpatialArgs args = new SpatialArgs(SpatialOperation.Intersects,
					          ctx.makeCircle(-80.0, 33.0, DistanceUtils.dist2Degrees(200, DistanceUtils.EARTH_MEAN_RADIUS_KM)));
			Filter filter = strategy.makeFilter(args);
			TopDocs docs = indexSearcher.search(new MatchAllDocsQuery(), filter, 10, idSort);
			
			for (ScoreDoc doc : docs.scoreDocs) {
				Document doc1 = indexSearcher.doc(doc.doc);
				String doc1Str = doc1.getField(strategy.getFieldName()).stringValue();
				int spaceIdx = doc1Str.indexOf(' ');
				double x = Double.parseDouble(doc1Str.substring(0, spaceIdx));
				double y = Double.parseDouble(doc1Str.substring(spaceIdx+1));
				double doc1DistDEG = ctx.calcDistance(args.getShape().getCenter(), x, y);
				System.out.println("x=>" + x + " y=>" + y + "distance=>" + doc1DistDEG);
			}
		}
		
		{
			Point pt = ctx.makePoint(60, -50);
			ValueSource valueSource = strategy.makeDistanceValueSource(pt, DistanceUtils.DEG_TO_KM);//the distance (in km)
			Sort distSort = new Sort(valueSource.getSortField(false)).rewrite(indexSearcher);//false=asc dist
			TopDocs docs = indexSearcher.search(new MatchAllDocsQuery(), 10, distSort);
			for (ScoreDoc doc : docs.scoreDocs) {
				Document doc1 = indexSearcher.doc(doc.doc);
				String doc1Str = doc1.getField(strategy.getFieldName()).stringValue();
				int spaceIdx = doc1Str.indexOf(' ');
				double x = Double.parseDouble(doc1Str.substring(0, spaceIdx));
				double y = Double.parseDouble(doc1Str.substring(spaceIdx+1));
				double doc1DistDEG = ctx.calcDistance(pt, x, y);
				System.out.println("x=>" + x + " y=>" + y + "distance=>" + doc1DistDEG);
			}
		}
		indexReader.close();
	}
	
	public static void main(String[] orgs) {
		NewLocation n = new NewLocation();
		n.init();
		try {
			n.indexPoints();
			n.search();
		} catch (IOException | ParseException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
}

从Lucene的doc中抄过来的.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值