有次在一个项目中有人提出了一种基于LBS业务的搜索的技术,lucene spatial搜索。随后在网上进行了大搜索。只搜索出一些lucene3代的小例子。现在lucene已经发到4.6了,3代明显太落后了。所以,进行lucene4 spatial的例子搜索,很不幸:使用的人太少了,没有一个例子。就连官网上也没有太多的说明。
由于没有仔细观看官网关于spatial模块的说明,未发现有用东西。一次不经意找到一行。位于API_Javadocs中spatial search的index.html上“For some sample code showing how to use the API, see SpatialExample.java in the tests.”
终于找到了入门的法宝。
SpatialExample
下面对其中使用到的核心类作下说明:
SpatialContext:空间模块上下文,们于spatial4j包中,一个全局单例对象。它是spatial4j的入口。它提供读写Shape对象的通道。
Shape:形状接口。
SpatialStrategy:lucene spatial模块提供创建查询Shape对象索途径。
package com.spatial.client; import java.io.File; import java.io.IOException; 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.document.TextField; 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.index.Term; import org.apache.lucene.search.Filter; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.TermQuery; 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.FSDirectory; import org.apache.lucene.util.Version; import com.chenlb.mmseg4j.analysis.SimpleAnalyzer; import com.spatial4j.core.context.SpatialContext; import com.spatial4j.core.distance.DistanceUtils; import com.spatial4j.core.shape.Shape; public class LuceneSpatialExample { public static void main(String[] args) throws IOException { new LuceneSpatialExample().test(); } public void test() throws IOException { init(); createIndex(); search(); } private SpatialContext ctx;//"ctx" is the conventional variable name private SpatialStrategy strategy; private Directory directory; private String indexPath = "E:\\index\\spatial\\"; protected void init() { //Typical geospatial context // These can also be constructed from SpatialContextFactory this.ctx = SpatialContext.GEO; int maxLevels = 11;//results in sub-meter precision for geohash //TODO demo lookup by detail distance // This can also be constructed from SpatialPrefixTreeFactory SpatialPrefixTree grid = new GeohashPrefixTree(ctx, maxLevels); this.strategy = new RecursivePrefixTreeStrategy(grid, "myGeoField"); try { this.directory = FSDirectory.open(new File(indexPath)); } catch (IOException e) { e.printStackTrace(); } } private void createIndex() throws IOException { IndexWriterConfig iwConfig = new IndexWriterConfig(Version.LUCENE_40,new SimpleAnalyzer()); IndexWriter indexWriter = new IndexWriter(directory, iwConfig); //Spatial4j is x-y order for arguments|对于参数的顺序是Longitude,Latitude indexWriter.addDocument(newSampleDocument(0, "一星大饭店",ctx.makePoint(116.430360,39.939686))); indexWriter.addDocument(newSampleDocument(1, "二星大饭店",ctx.makePoint( 116.430319,39.939702))); indexWriter.addDocument(newSampleDocument(2, "三星大饭店",ctx.makePoint(116.430459,39.939802))); indexWriter.addDocument(newSampleDocument(3, "四星大饭店", ctx.makePoint(116.430449,39.939902))); indexWriter.addDocument(newSampleDocument(4, "六星大饭店",ctx.makePoint(116.430439,39.93402))); indexWriter.addDocument(newSampleDocument(5, "七星大饭店",ctx.makePoint(116.430419,39.934102))); indexWriter.addDocument(newSampleDocument(6, "五星大饭店",ctx.makePoint(116.430429,39.934202))); indexWriter.addDocument(newSampleDocument(6, "五星大酒店",ctx.makePoint(115.430429,39.934202))); indexWriter.commit(); indexWriter.close(); } private Document newSampleDocument(int id,String keyword, Shape... shapes) { Document doc = new Document(); doc.add(new IntField("id", id, Field.Store.YES)); //Potentially more than one shape in this field is supported by some // strategies; see the javadocs of the SpatialStrategy impl to see. for (Shape shape : shapes) { for (IndexableField f : strategy.createIndexableFields(shape)) { doc.add(f); } //store it too; the format is up to you doc.add(new StoredField(strategy.getFieldName(), ctx.toString(shape))); } doc.add(new TextField("keyword",keyword, Field.Store.YES)); return doc; } private void search() throws IOException { IndexReader indexReader = DirectoryReader.open(directory); IndexSearcher indexSearcher = new IndexSearcher(indexReader); { //16米范围内 SpatialArgs args = new SpatialArgs(SpatialOperation.Intersects, ctx.makeCircle(116.430459,39.939802, DistanceUtils.dist2Degrees(0.016,DistanceUtils.EARTH_MEAN_RADIUS_KM))); Filter filter = strategy.makeFilter(args); Term term = new Term("keyword","饭店"); Query query001 = new TermQuery(term); TopDocs docs = indexSearcher.search(query001,filter,1000); System.out.println(docs.totalHits); ScoreDoc[] scoreDoc = docs.scoreDocs; if(docs.totalHits>0) for (int i = 0; i < scoreDoc.length; i++) { int doc = scoreDoc[i].doc; Document mydoc = indexReader.document(doc); System.out.println(mydoc.get("myGeoField")); String value = mydoc.get("myGeoField"); String []lonlat = value.split(" "); double eLat = Double.valueOf(lonlat[1]); double eLon = Double.valueOf(lonlat[0]); System.out.println(SpatialUtils.getDistance(39.939802, 116.430459, eLat, eLon, false)+"|keyword: "+mydoc.get("keyword")); } } indexReader.close(); } }
lucene spatial 模块本身就是一个Filter的实现。核心还是lucene的全文检索。真正理解学习新框架或新开源的东西就得从TestCase看起。
相关推荐
icu4j-4_8.jar jakarta-regexp-1.4.jar junit-4.7.jar lucene-analyzers-3.3.0.jar lucene-benchmark-3.3.0.jar lucene-core-3.3.0.jar lucene-demo-3.3.0.jar lucene-grouping-3.3.0.jar lucene-highlighter-3.3.0....
这主要依赖于`Spatial4j`库来处理地理坐标,并结合Lucene的索引结构,实现了高效的空间查询。 2. **空间索引类型**:Lucene支持多种空间索引策略,如Grid-based(基于网格)和Tree-based(基于树)等,以优化不同...
1. **集成Lucene**:首先,将Lucene相关的jar包添加到Android项目的依赖中,这可能包括基础的Lucene核心库和其他扩展模块,如spatial4j和geohash库。 2. **构建索引**:创建一个索引,包含文档(如商店、餐馆等)的...
5.1.1.jar,log4j-api-2.7.jar,log4j-core-2.7.jar,lucene-analyzers-common-6.3.0.jar,lucene-backward-codecs-6.3.0.jar,lucene-core-6.3.0.jar,lucene-grouping-6.3.0.jar,lucene-highlighter-6.3.0.jar,lucene-...
5.1.1.jar,log4j-1.2-api-2.7.jar,log4j-api-2.7.jar,log4j-core-2.7.jar,lucene-analyzers-common-6.4.1.jar,lucene-backward-codecs-6.4.1.jar,lucene-core-6.4.1.jar,lucene-grouping-6.4.1.jar,lucene-...
SSE4J(Spatial Search Engine for Java)是针对地理信息数据源构建的垂直搜索引擎应用接口,是基于Lucene+JTS Topology Suite开源库设计的框架。 规划的SSE4J包含: 1)SSE4J应用开发包 2)SSE4J Webservice应用...
SSE4J(Spatial Search Engine for Java)是针对地理信息数据源构建的垂直搜索引擎应用接口,是基于Lucene+JTS Topology Suite开源库设计的框架。 规划的SSE4J包含: 1)SSE4J应用开发包 2)SSE4J Webservice应用...
SSE4J(Spatial Search Engine for Java)是针对地理信息数据源构建的垂直搜索引擎应用接口,是基于Lucene+JTS Topology Suite开源库设计的框架。 规划的SSE4J包含: 1)SSE4J应用开发包 2)SSE4J Webservice应用...
6. **JVM和Java相关库**:Solr运行在Java虚拟机上,因此需要依赖一些Java标准库,如`log4j.jar`用于日志记录,`slf4j-api*.jar`和`slf4j-log4j*.jar`为SLF4J(Simple Logging Facade for Java)接口和适配器。...
【SSE4J】全称为Spatial Search Engine for Java,是一个针对地理信息数据源的垂直搜索引擎应用接口。它基于Java Lucene(一个全文搜索引擎库)和JTS Topology Suite(一个用于地理空间分析的Java库)设计。SSE4J的...