1 package test.test; 2 3 import java.io.BufferedReader; 4 import java.io.File; 5 import java.io.IOException; 6 import java.io.InputStreamReader; 7 import java.util.Date; 8 9 import org.apache.lucene.analysis.Analyzer; 10 import org.apache.lucene.document.Document; 11 import org.apache.lucene.document.DoubleField; 12 import org.apache.lucene.document.Field; 13 import org.apache.lucene.document.StringField; 14 import org.apache.lucene.document.Field.Store; 15 import org.apache.lucene.document.TextField; 16 import org.apache.lucene.index.DirectoryReader; 17 import org.apache.lucene.index.IndexReader; 18 import org.apache.lucene.index.IndexWriter; 19 import org.apache.lucene.index.IndexWriterConfig; 20 import org.apache.lucene.queryparser.classic.ParseException; 21 import org.apache.lucene.queryparser.classic.QueryParser; 22 import org.apache.lucene.search.Filter; 23 import org.apache.lucene.search.IndexSearcher; 24 import org.apache.lucene.search.Query; 25 import org.apache.lucene.search.ScoreDoc; 26 import org.apache.lucene.search.TopDocs; 27 import org.apache.lucene.spatial.SpatialStrategy; 28 import org.apache.lucene.spatial.prefix.RecursivePrefixTreeStrategy; 29 import org.apache.lucene.spatial.prefix.tree.GeohashPrefixTree; 30 import org.apache.lucene.spatial.prefix.tree.SpatialPrefixTree; 31 import org.apache.lucene.spatial.query.SpatialArgs; 32 import org.apache.lucene.spatial.query.SpatialOperation; 33 import org.apache.lucene.store.Directory; 34 import org.apache.lucene.store.FSDirectory; 35 import org.apache.lucene.util.Version; 36 import org.wltea.analyzer.lucene.IKAnalyzer; 37 38 import com.spatial4j.core.context.SpatialContext; 39 import com.spatial4j.core.distance.DistanceUtils; 40 import com.spatial4j.core.shape.Point; 41 import com.spatial4j.core.shape.impl.PointImpl; 42 43 public class Index_test { 44 45 /** 46 * If you want a typical geodetic context, just reference GEO. 47 * */ 48 private static SpatialContext ctx = SpatialContext.GEO; 49 50 51 52 53 private static SpatialPrefixTree spatialPrefixTree = new GeohashPrefixTree(ctx, 11); 54 55 /** 56 * 抽象类 57 * 空间检索的主要类 58 * spatialstrategy封装了基于形状检索的方法,以及基于形状过滤器的方法。 59 * */ 60 private static SpatialStrategy spatialStrategy = new RecursivePrefixTreeStrategy(spatialPrefixTree, "fieldName"); 61 62 63 private static String indexPath = "/home/xy/study/index/"; 64 65 private static void buildIndex() throws IOException { 66 67 Directory directory = FSDirectory.open(new File(indexPath)); 68 Analyzer ikAnalyzer = new IKAnalyzer();//分析器 名称 69 IndexWriterConfig iwConfig = new IndexWriterConfig(Version.LUCENE_46, ikAnalyzer); 70 IndexWriter indexWriter = new IndexWriter(directory, iwConfig); 71 72 73 BufferedReader br = null; 74 try { 75 // 逐行添加测试数据到索引中,测试数据文件和源文件在同一个目录下 76 br = new BufferedReader(new InputStreamReader( 77 Index_test.class.getResourceAsStream("data"))); 78 79 80 int count = 0; 81 String line = null; 82 while ((line = br.readLine()) != null) { 83 String[] strarr = line.split("\t"); 84 85 Document doc = new Document(); 86 double lng = Double.parseDouble(strarr[2]); 87 double lat = Double.parseDouble(strarr[3]); 88 89 90 91 //StringField 与 TextField区别,TextField会分词存储,StringField为不分词存储 92 doc.add(new StringField("myid", strarr[0], Store.YES)); 93 doc.add(new TextField("name", strarr[1], Store.YES)); 94 doc.add(new DoubleField("lng", lng, Store.YES)); 95 doc.add(new DoubleField("lat", lat, Store.YES)); 96 97 //创建图形索引,如果不创建,图形过滤器将失去效果,即为图形过滤器做准备 98 Field[] fields = spatialStrategy.createIndexableFields(ctx.makePoint(lng, lat)); 99 for(Field field:fields){ 100 doc.add(field); 101 } 102 103 indexWriter.addDocument(doc); 104 count++; 105 } 106 107 System.out.println("创建缓存:"+count); 108 } catch (Exception e) { 109 e.printStackTrace(); 110 } finally { 111 if (br != null) { 112 try { 113 br.close(); 114 indexWriter.commit(); 115 indexWriter.close(); 116 } catch (IOException e) { 117 e.printStackTrace(); 118 } 119 } 120 } 121 } 122 123 124 125 126 private static void search() throws IOException, ParseException { 127 String keyword = "美发"; 128 double lng = 116.3838183,lat = 39.9629015 ,distance = 300.0; 129 // 130 Directory dir = FSDirectory.open(new File(indexPath)); 131 IndexReader indexReader = DirectoryReader.open(dir); 132 133 IndexSearcher indexSearcher = new IndexSearcher(indexReader); 134 135 136 // Point point = new PointImpl(lng, lat, ctx); 137 //以point为中心,半径为0.3km为半径 138 SpatialArgs args = new SpatialArgs(SpatialOperation.Intersects,ctx.makeCircle(lng,lat, DistanceUtils.dist2Degrees( 139 distance / 1000.0, DistanceUtils.EARTH_MEAN_RADIUS_KM))); 140 141 Analyzer ikAnalyzer = new IKAnalyzer();//分词 名称 142 QueryParser queryParser = new QueryParser(Version.LUCENE_46,"name", ikAnalyzer); 143 Query query = queryParser.parse(keyword); 144 //图形过滤器 145 Filter filter = spatialStrategy.makeFilter(args); 146 TopDocs topDocs = indexSearcher.search(query, filter, 100); 147 148 149 System.out.println("总找到:"+topDocs.totalHits); 150 151 152 ScoreDoc[] scoreDocs = topDocs.scoreDocs; 153 for(ScoreDoc scoreDoc:scoreDocs){ 154 int doc = scoreDoc.doc; 155 Document document = indexReader.document(doc); 156 System.out.println(document.get("myid")+"\t"+document.get("name")+"\t"+document.get("lng")+"\t"+document.get("lat")+"\t"+scoreDoc.score); 157 } 158 } 159 160 161 162 163 164 165 166 private static void search_2() throws IOException, ParseException { 167 String keyword = "30"; 168 double lng = 116.3838183,lat = 39.9629015 ,distance = 3000.0; 169 // 170 Directory dir = FSDirectory.open(new File(indexPath)); 171 IndexReader indexReader = DirectoryReader.open(dir); 172 173 IndexSearcher indexSearcher = new IndexSearcher(indexReader); 174 175 SpatialArgs args = new SpatialArgs(SpatialOperation.Intersects,ctx.makeCircle(lng, lat, DistanceUtils.dist2Degrees( 176 distance / 1000.0, DistanceUtils.EARTH_MEAN_RADIUS_KM))); 177 // Filter filter = spatialStrategy.makeFilter(args); 178 179 180 Analyzer ikAnalyzer = new IKAnalyzer();//分词 名称 181 QueryParser queryParser = new QueryParser(Version.LUCENE_46,"myid", ikAnalyzer); 182 Query query = queryParser.parse(keyword); 183 184 TopDocs topDocs = indexSearcher.search(query, null, 10); 185 186 187 System.out.println("总找到:"+topDocs.totalHits); 188 189 190 ScoreDoc[] scoreDocs = topDocs.scoreDocs; 191 for(ScoreDoc scoreDoc:scoreDocs){ 192 int doc = scoreDoc.doc; 193 Document document = indexReader.document(doc); 194 System.out.println(document.get("myid")+"\t"+document.get("name")+"\t"+document.get("lng")+"\t"+document.get("lat")+"\t"+scoreDoc.score); 195 } 196 197 } 198 199 200 201 202 public static void main(String[] args) { 203 try { 204 205 // buildIndex(); 206 207 208 // long l1 = new Date().getTime(); 209 // search(); 210 // long l2 = new Date().getTime(); 211 // System.out.println(l2 - l1); 212 213 search_2(); 214 } catch (Exception e) { 215 e.printStackTrace(); 216 } 217 218 } 219
测试数据
12 时尚码头美容美发热烫特价 116.3838183 39.9629015 17 审美个人美容美发套餐 116.386564 39.966102 23 海底捞吃300送300 116.38629 39.9629573 26 仅98元!享原价335元李老爹 116.3846175 39.9629125 29 都美造型烫染美发护理套餐 116.38629 39.9629573 30 仅售55元!原价80元的老舍茶馆相声下午场 116.0799914 39.9655391 33 仅售55元!原价80元的新笑声客栈早场 116.0799914 39.9655391 34 仅售39元(红色礼盒)!原价80元的平谷桃 116.0799914 39.9655391 46 仅售38元!原价180元地质礼堂白雪公主 116.0799914 39.9655391 49 仅99元!享原价342.7元自助餐 116.0799914 39.9655391 58 桑海教育暑期学生报名培训九折优惠券 116.0799914 39.9655391 59 全国发货:仅29元!贝玲妃超模粉红高光光 116.0799914 39.9655391 65 海之屿生态水族用品店抵用券 116.0799914 39.9655391 67 小区东门时尚烫染个人护理美发套餐 116.3799914 39.9655391 74 《郭德纲相声专辑》CD套装 116.0799915 39.9655391
220 }