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(" ");
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")+" "+document.get("name")+" "+document.get("lng")+" "+document.get("lat")+" "+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")+" "+document.get("name")+" "+document.get("lng")+" "+document.get("lat")+" "+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 }