个人博客站已经上线了,网址 www.llwjy.com ~欢迎各位吐槽
在之前的《基于lucene的案例开发:Query查询》这篇博客中对实际开发过程中比较常见的Query做了简单的介绍,这里就介绍下具体的代码实现。查看最新代码点击这里或访问 http://www.llwjy.com/source/com.lulei.lucene.query.PackQuery.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396 1/**
2 *@Description: 创建查询Query
3 */
4package com.lulei.lucene.query;
5
6import java.io.IOException;
7import java.io.StringReader;
8import java.util.ArrayList;
9
10import org.apache.lucene.analysis.Analyzer;
11import org.apache.lucene.analysis.TokenStream;
12import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
13import org.apache.lucene.index.Term;
14import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
15import org.apache.lucene.queryparser.classic.ParseException;
16import org.apache.lucene.queryparser.classic.QueryParser;
17import org.apache.lucene.search.BooleanClause.Occur;
18import org.apache.lucene.search.BooleanQuery;
19import org.apache.lucene.search.NumericRangeQuery;
20import org.apache.lucene.search.PhraseQuery;
21import org.apache.lucene.search.PrefixQuery;
22import org.apache.lucene.search.Query;
23import org.apache.lucene.search.TermQuery;
24import org.apache.lucene.search.TermRangeQuery;
25import org.apache.lucene.search.WildcardQuery;
26import org.apache.lucene.util.Version;
27
28import com.lulei.lucene.index.manager.IndexManager;
29
30
31public class PackQuery {
32 //分词器
33 private Analyzer analyzer;
34 //使用索引中的分词器
35 public PackQuery(String indexName) {
36 analyzer = IndexManager.getIndexManager(indexName).getAnalyzer();
37 }
38 //使用自定义分词器
39 public PackQuery(Analyzer analyzer) {
40 this.analyzer = analyzer;
41 }
42
43 /**
44 * @param key
45 * @param fields
46 * @return Query
47 * @throws ParseException
48 * @Author: lulei
49 * @Description: 查询字符串匹配多个查询域
50 */
51 public Query getMultiFieldQuery(String key, String[] fields) throws ParseException{
52 MultiFieldQueryParser parse = new MultiFieldQueryParser(Version.LUCENE_43, fields, analyzer);
53 Query query = null;
54 query = parse.parse(key);
55 return query;
56 }
57
58 /**
59 * @param key
60 * @param field
61 * @return Query
62 * @throws ParseException
63 * @Author: lulei
64 * @Description: 查询字符串匹配单个查询域
65 */
66 public Query getOneFieldQuery(String key, String field) throws ParseException{
67 if (key == null || key.length() < 1){
68 return null;
69 }
70 QueryParser parse = new QueryParser(Version.LUCENE_43, field, analyzer);
71 Query query = null;
72 query = parse.parse(key);
73 return query;
74 }
75
76 /**
77 * @param key
78 * @param fields
79 * @param occur
80 * @return Query
81 * @throws IOException
82 * @Author: lulei
83 * @Description: 查询字符串、多个查询域以及查询域在查询语句中的关系
84 */
85 public Query getBooleanQuery(String key, String[] fields, Occur[] occur) throws IOException{
86 if (fields.length != occur.length){
87 System.out.println("fields.length isn't equals occur.length, please check params!");
88 return null;
89 }
90 BooleanQuery query = new BooleanQuery();
91 TokenStream tokenStream = analyzer.tokenStream("", new StringReader(key));
92 ArrayList<String> analyzerKeys = new ArrayList<String>();
93 while(tokenStream.incrementToken()){
94 CharTermAttribute term = tokenStream.getAttribute(CharTermAttribute.class);
95 analyzerKeys.add(term.toString());
96 }
97 for(int i = 0; i < fields.length; i++){
98 BooleanQuery queryField = new BooleanQuery();
99 for(String analyzerKey : analyzerKeys){
100 TermQuery termQuery = new TermQuery(new Term(fields[i], analyzerKey));
101 queryField.add(termQuery, Occur.SHOULD);
102 }
103 query.add(queryField, occur[i]);
104 }
105 return query;
106 }
107
108 /**
109 * @param querys
110 * @param occur
111 * @return Query
112 * @Author: lulei
113 * @Description: 组合多个查询,之间的关系由occur确定
114 */
115 public Query getBooleanQuery(ArrayList<Query> querys, ArrayList<Occur> occurs){
116 if (querys.size() != occurs.size()){
117 System.out.println("querys.size() isn't equals occurs.size(), please check params!");
118 return null;
119 }
120 BooleanQuery query = new BooleanQuery();
121 for (int i = 0; i < querys.size(); i++){
122 query.add(querys.get(i), occurs.get(i));
123 }
124 return query;
125 }
126
127 /**
128 * @param fieldName
129 * @param value
130 * @return
131 * @Author: lulei
132 * @Description: StringField属性的搜索
133 */
134 public Query getStringFieldQuery(String value, String fieldName){
135 Query query = null;
136 query = new TermQuery(new Term(fieldName, value));
137 return query;
138 }
139
140 /**
141 * @param fields
142 * @param values
143 * @return
144 * @Author: lulei
145 * @Description: 多个StringField属性的搜索
146 */
147 public Query getStringFieldQuery(String[] values, String[] fields, Occur occur){
148 if (fields == null || values == null || fields.length != values.length){
149 return null;
150 }
151 ArrayList<Query> querys = new ArrayList<Query>();
152 ArrayList<Occur> occurs = new ArrayList<Occur>();
153 for (int i = 0; i < fields.length; i++){
154 querys.add(getStringFieldQuery(values[i], fields[i]));
155 occurs.add(occur);
156 }
157 return getBooleanQuery(querys, occurs);
158 }
159
160 /**
161 * @param key
162 * @param field
163 * @param lucene43
164 * @return
165 * @throws ParseException
166 * @Author: lulei
167 * @Description: 查询字符串和单个查询域 QueryParser是否使用4.3
168 */
169 public Query getOneFieldQuery(String key, String field, boolean lucene43) throws ParseException{
170 if (key == null || key.length() < 1){
171 return null;
172 }
173 if (lucene43){
174 return getOneFieldQuery(key, field);
175 }
176 @SuppressWarnings("deprecation")
177 QueryParser parse = new QueryParser(Version.LUCENE_30, field, analyzer);
178 Query query = null;
179 query = parse.parse(key);
180 return query;
181 }
182
183 /**
184 * @param key
185 * @param field
186 * @Author: lulei
187 * @Description: key开头的查询字符串,和单个域匹配
188 */
189 public Query getStartQuery(String key, String field) {
190 if (key == null || key.length() < 1){
191 return null;
192 }
193 Query query = new PrefixQuery(new Term(field, key));
194 return query;
195 }
196
197 /**
198 * @param key
199 * @param fields
200 * @param occur
201 * @Author: lulei
202 * @Description: key开头的查询字符串,和多个域匹配,每个域之间的关系由occur确定
203 */
204 public Query getStartQuery(String key, String []fields, Occur occur){
205 if (key == null || key.length() < 1){
206 return null;
207 }
208 ArrayList<Query> querys = new ArrayList<Query>();
209 ArrayList<Occur> occurs = new ArrayList<Occur>();
210 for (String field : fields) {
211 querys.add(getStartQuery(key, field));
212 occurs.add(occur);
213 }
214 return getBooleanQuery(querys, occurs);
215 }
216
217 /**
218 * @param key
219 * @param fields
220 * @Author: lulei
221 * @Description: key开头的查询字符串,和多个域匹配,每个域之间的关系Occur.SHOULD
222 */
223 public Query getStartQuery(String key, String []fields) {
224 return getStartQuery(key, fields, Occur.SHOULD);
225 }
226
227 /**
228 * @param key
229 * @param field
230 * @param slop
231 * @return
232 * @Author:lulei
233 * @Description: 自定每个词元之间的最大距离
234 */
235 public Query getPhraseQuery(String key, String field, int slop) {
236 if (key == null || key.length() < 1){
237 return null;
238 }
239 StringReader reader = new StringReader(key);
240 PhraseQuery query = new PhraseQuery();
241 query.setSlop(slop);
242 try {
243 TokenStream tokenStream = this.analyzer.tokenStream(field, reader);
244 tokenStream.reset();
245 CharTermAttribute term = tokenStream.getAttribute(CharTermAttribute.class);
246 while(tokenStream.incrementToken()){
247 query.add(new Term(field, term.toString()));
248 }
249 reader.close();
250 } catch (IOException e) {
251 e.printStackTrace();
252 return null;
253 }
254 return query;
255 }
256
257 /**
258 * @param key
259 * @param fields
260 * @param slop
261 * @param occur
262 * @return
263 * @Author:lulei
264 * @Description: 自定每个词元之间的最大距离,查询多个域,每个域之间的关系由occur确定
265 */
266 public Query getPhraseQuery(String key, String[] fields, int slop, Occur occur) {
267 if (key == null || key.length() < 1){
268 return null;
269 }
270 ArrayList<Query> querys = new ArrayList<Query>();
271 ArrayList<Occur> occurs = new ArrayList<Occur>();
272 for (String field : fields) {
273 querys.add(getPhraseQuery(key, field, slop));
274 occurs.add(occur);
275 }
276 return getBooleanQuery(querys, occurs);
277 }
278
279 /**
280 * @param key
281 * @param fields
282 * @param slop
283 * @return
284 * @Author:lulei
285 * @Description: 自定每个词元之间的最大距离,查询多个域,每个域之间的关系是Occur.SHOULD
286 */
287 public Query getPhraseQuery(String key, String[] fields, int slop) {
288 return getPhraseQuery(key, fields, slop, Occur.SHOULD);
289 }
290
291 /**
292 * @param key
293 * @param field
294 * @return
295 * @Author:lulei
296 * @Description: 通配符检索 eg:getWildcardQuery("a*thor", "field")
297 */
298 public Query getWildcardQuery(String key, String field) {
299 if (key == null || key.length() < 1){
300 return null;
301 }
302 return new WildcardQuery(new Term(field, key));
303 }
304
305 /**
306 * @param key
307 * @param fields
308 * @param occur
309 * @return
310 * @Author:lulei
311 * @Description: 通配符检索,域之间的关系为occur
312 */
313 public Query getWildcardQuery(String key, String[] fields, Occur occur) {
314 if (key == null || key.length() < 1){
315 return null;
316 }
317 ArrayList<Query> querys = new ArrayList<Query>();
318 ArrayList<Occur> occurs = new ArrayList<Occur>();
319 for (String field : fields) {
320 querys.add(getWildcardQuery(key, field));
321 occurs.add(occur);
322 }
323 return getBooleanQuery(querys, occurs);
324 }
325
326 /**
327 * @param key
328 * @param fields
329 * @return
330 * @Author:lulei
331 * @Description: 通配符检索,域之间的关系为Occur.SHOULD
332 */
333 public Query getWildcardQuery(String key, String[] fields) {
334 return getWildcardQuery(key, fields, Occur.SHOULD);
335 }
336
337 /**
338 * @param keyStart
339 * @param keyEnd
340 * @param field
341 * @param includeStart
342 * @param includeEnd
343 * @return
344 * @Author:lulei
345 * @Description: 范围搜索
346 */
347 public Query getRangeQuery (String keyStart, String keyEnd, String field, boolean includeStart, boolean includeEnd) {
348 return TermRangeQuery.newStringRange(field, keyStart, keyEnd, includeStart, includeEnd);
349 }
350
351 /**
352 * @param min
353 * @param max
354 * @param field
355 * @param includeMin
356 * @param includeMax
357 * @return
358 * @Author:lulei
359 * @Description: 范围搜索
360 */
361 public Query getRangeQuery (int min, int max, String field, boolean includeMin, boolean includeMax) {
362 return NumericRangeQuery.newIntRange(field, min, max, includeMin, includeMax);
363 }
364
365 /**
366 * @param min
367 * @param max
368 * @param field
369 * @param includeMin
370 * @param includeMax
371 * @return
372 * @Author:lulei
373 * @Description: 范围搜索
374 */
375 public Query getRangeQuery (float min, float max, String field, boolean includeMin, boolean includeMax) {
376 return NumericRangeQuery.newFloatRange(field, min, max, includeMin, includeMax);
377 }
378
379 /**
380 * @param min
381 * @param max
382 * @param field
383 * @param includeMin
384 * @param includeMax
385 * @return
386 * @Author:lulei
387 * @Description: 范围搜索
388 */
389 public Query getRangeQuery (double min, double max, String field, boolean includeMin, boolean includeMax) {
390 return NumericRangeQuery.newDoubleRange(field, min, max, includeMin, includeMax);
391 }
392
393 public static void main(String[] args) throws IOException {
394 }
395}
396
PackQuery类的构造方法,可以手动指定分词器也可以使用索引的分词器。个人建议,在项目中使用索引中的分词器,这样就不会因为分词器的不同造成不知名的错误。
ps:最近发现其他网站可能会对博客转载,上面并没有源链接,如想查看更多关于 基于lucene的案例开发 请http://www.aiuxian.com/catalog/p-322798.html。或访问网址http://blog.csdn.net/xiaojimanman/article/category/2841877