Solr入門和實踐以及我對Solr的8點理解

友情提示
Solr的內容仍是比較多的,一篇文章只能講解一部分。
全面介紹,沒興趣,沒時間,也沒能力,回報還不大。
本文只寫點我認爲比較重要的知識點,獨特的我的想法。
僅供參考哦,更多細節須要本身去琢磨。


轉自:http://www.2cto.com/kf/201511/451412.htmlhtml



概述前端

Solr是一個高性能,採用 Java 5開發,基於Lucene的全文搜索服務器。同時對其進行了擴展,提供了比Lucene更爲豐富的查詢語言,
同時實現了可配置、可擴展並對查詢性能進行了優化,而且提供了一個完善的功能管理界面,是一款很是優秀的全文搜索引擎。


工做方式
文檔經過Http利用XML 加到一個搜索集合中。
查詢該集合也是經過http收到一個XML/JSON響應來實現。
它的主要特性包括:高效、靈活的緩存功能,垂直搜索功能,高亮顯示搜索結果,經過索引複製來提升可用性,
提供一套強大Data Schema來定義字段,類型和設置文本分析,提供基於Web的管理界面等。


需求場景
查詢和搜索,咱們直接查詢 數據庫 MySQL。查詢數據庫主要有一些侷限性:
好比多表查詢效率低,大文本字段很差創建索引和搜索,複雜的條件查詢和搜索功能不夠強大,或者說不夠簡單。
使用Solr的話,就很簡單地解決了以上問題。

以上需求,或者說關係型數據庫 mysql 的問題,只是目前的一點理解。
雖然說可以使用MySQL和Sorl解決實際中的問題,但畢竟都是中低難度的問題(自認爲如此哦)。
非要說深刻理解,剖析Solr的好處,MySQL是否「乾的過」Solr,真心不懂。
單獨搞MySQL,夠你研究5年以上,DBA畢竟是個傳說。
Solr,想搞懂,也得好多年。

我的同時學習Java服務端、 Android 、iOS、Web前端,目標是可以解決工做中最多見的問題,並不想要
深刻學習有限的幾種技術,好比MySQL,達到那種「再難的問題,也能夠搞定」的程度。


我對Solr的8點理解
1.定義數據源接口,得到數據。

好比定義MySQL查詢語句,把一個表或多個表的數據,導入到Solr中。
這個地方我以爲特別「不公平」,數據都是從別的地方搞過來的。外界的數據若是會變化,意味着,必須處理「數據同步」。
實時性要求不高的狀況下,能夠天天「全量更新」。要求高的狀況下,單條數據的變化,須要「實時更新-單條」。
所以,Solr和Mysql並非「直接競爭」關係,而是「互補」的關係。
2.把Mysql等數據源的數據,導入到Solr中去。
Solr定義數據,能夠理解成一張很大的表,包含了不少字段,好比能夠包含mysql中3個表的全部字段。
這樣,查詢就不存在「多表」的問題。
既然是一張表,創建索引,查詢就很快了。
3.自帶緩存功能。
Mysql,Solr,Redis等數據源或者有能力得到數據和管理數據的 組件 ,只要須要,就能夠提供「緩存」功能。
Solr簡化了查詢,緩存就更容易了。
4.索引和全文搜索。
Solr底層採用Lucene創建索引,全文索引,這樣能夠實現更多的「搜索功能」,能夠說加強了Mysql的查詢。
5.站內搜索的另一種形式。
百度等搜索引擎,能夠爲網站提供「站內搜索」功能,他們爬去數據能夠是公開的URL的形式。
若是須要和百度等合做,能夠申請使用百度的搜索API,將站內數據,更友好,更快速地告訴百度。
而Solr和百度提供的搜索相關接口就基本同樣,只不過是處在咱們的管理之下。
6.簡潔使用的管理界面。
後臺有Web界面,導入數據,更新,能夠經過可視化的操做來管理,比較方便。
7.功能服務化。
Solr提供的查詢等功能,有Java等多種語言的實現。
創建數據結構,導入數據,維護緩存和實時性,最重要的就是「查詢」和「搜索」了。
8.最大的「隱患」。
只用Mysql管理數據和查詢的時候,咱們必須而且只須要保障mysql的「高可用性」。
不能出任何問題,若是隻用1個Mysql,意味着咱們須要實時監控Mysql是否可用,若是出了問題,咱們須要當即修復它。
若是是多臺Mysql,咱們須要用主從,或者更復雜的主從。

如今用了Solr,意味着,咱們不少查詢和搜索,優先使用Solr,再也不使用Mysql。
這個時候,爲了「高可靠性」,咱們也必須保障Solr是靠譜的。
單臺Solr服務器,可靠性怎麼樣,我不太清楚。
不管單臺Solr是否靠譜,多臺Solr更加靠譜,這都意味着
「咱們程序中必須可靠的基礎服務更多了」。

常見的必須「高可用性」的服務有
a.Mysql
b.Redis
3.Nginx
4.Solr
高可用性的服務越多,意味着咱們的程序越複雜。
大部分的公司,都是中小型企業。
大部分的應用,都是爲了快速推出,看看是否有效果。
真正須要保障「高可靠性」的項目,是不多的,若是遇到了,是很幸運的。

官方網站 :http://lucene.apache.org/solr/
本地環境:Windows-5.3.1版本

運行和創建工程
啓動:solr.cmd start(相似這樣)
創建工程:
name=raikou
config=solrconfig.xml
schema=schema.xml
dataDir=J:\SoftData\Solr\raikou\data
指定config、schema等多種參數。
(圖文並茂的入門指引,能夠參考其它博主的文章,本人以爲這種「圖文並茂」的太尼瑪費事了。
方便了讀者,可是「技術含量」不夠高,博主表示不過癮o(︶︿︶)o )


簡要介紹下幾個配置,附帶源文件內容


core.properties
?
1
2
3
4
name=raikou(項目名稱)
config=solrconfig.xml(Solr配置)
schema=schema.xml(模式定義)
dataDir=J:\SoftData\Solr\raikou\data (存儲索引等數據)




Web界面輸入的內容,保存在這了,入口配置,能夠這麼說。


schema.xml
?
1
2
3
4
<field indexed= "true" multivalued= "false" name= "id" required= "true" stored= "true" type= "long" >
<field indexed= "true" name= "title" required= "true" stored= "true" type= "string" >
<field indexed= "true" name= "content" stored= "true" type= "string" >
<field indexed= "true" name= "summary" stored= "true" type= "string" > </field></field></field></field>


定義了幾個字段


id
title
惟一字段,默認查詢字段

schemal.xml還配置了若干其它配置文件,好比「stopwords_en.txt」、「protwords.txt」、「stopwords.txt」等。
若是Solr啓動報錯,多是缺乏了這些字段。

data-config.xml
?
1
2
3
4
5
6
7
8
9
<!--?xml version= 1.0 encoding=UTF- 8 ?--> 
<dataconfig> 
<datasource driver= "com.mysql.jdbc.Driver" password= "mypassword/" type= "JdbcDataSource" url= "jdbc:mysql://localhost:3306/raikou?useUnicode=true&characterEncoding=UTF-8" user= "root"
   
<document name= "raikou_article" >          
     <entity deltaimportquery= "select" deltaquery= "select" from= "" id= "${dih.delta.id}" name= "raikou_article" query= "select" raikou_article= "" update_time= "" where= "" > '${dataimporter.last_index_time}' >                   
                 <field column= "id" name= "id"
                 <field column= "title" name= "title" >
</field></field></entity></document></datasource></dataconfig>

定義了數據導入、增量更新的查詢語句。

web.xml 這段配置,可能有用
E:Mongodb-Redis-Nginxsolr-5.3.1serversolr-webappwebappWEB-INFweb.xml
?
1
2
3
4
5
6
7
8
9
<!-- People who want to hardcode their Solr Home directly into the
       WAR File can set the JNDI property here...
   -->
  
    <env-entry>
       <env-entry-name>solr/home</env-entry-name>
       <env-entry-value>J:SoftDataSolr</env-entry-value>
       <env-entry-type>java.lang.String</env-entry-type>
    </env-entry>



Java程序訪問
maven配置

?
1
2
3
4
5
<dependency>
         <groupid>org.apache.solr</groupid>
         solr-solrj</artifactid>
         <version> 5.3 . 1 </version>
     </dependency>




包名:org.apache.solr.client.solrj


工具類
SolrHelper.java 查詢(查詢語句構造和執行查詢,分頁查詢),更新,重建索引

?
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
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
 
 
import org.apache.commons.lang3.StringUtils;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrInputDocument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
 
import com.github.pagehelper.Page;
 
 
/**查詢(查詢語句構造),更新,重建索引*/
public class SolrHelper<t> {
 
 
     protected final Logger logger = LoggerFactory.getLogger(SolrHelper. class );
 
 
     private HttpSolrClient server;
 
 
     private StringBuffer queryString;
 
 
     public SolrHelper(String reqUrl) {
         server = new HttpSolrClient(reqUrl);
         queryString = new StringBuffer();
     }
 
 
     public void andEquals(String fieldName, String val) {
         queryString.append( && ).append(fieldName).append(:).append(val);
     }
 
 
     public void orEquals(String fieldName, String val) {
         queryString.append( || ).append(fieldName).append(:).append(val);
     }
 
 
     public void andNotEquals(String fieldName, String val) {
         queryString.append( && ).append(-).append(fieldName).append(:)
                 .append(val);
     }
 
 
     public void orNotEquals(String fieldName, String val) {
         queryString.append( || ).append(-).append(fieldName).append(:)
                 .append(val);
     }
 
 
     public void andGreaterThan(String fieldName, String val) {
         queryString.append( && ).append(fieldName).append(:[).append(val)
                 .append( TO ).append(*]);
     }
 
 
     public void orGreaterThan(String fieldName, String val) {
         queryString.append( || ).append(fieldName).append(:[).append(val)
                 .append( TO ).append(*]);
     }
 
 
     public void andGreaterThanOrEqualTo(String fieldName, String val) {
         queryString.append( && ).append(fieldName).append(:[).append(val)
                 .append( TO ).append(*]);
     }
 
 
     public void orGreaterThanOrEqualTo(String fieldName, String val) {
         queryString.append( || ).append(fieldName).append(:[).append(val)
                 .append( TO ).append(*]);
     }
 
 
     public void andDateGreaterThan(String fieldName, Date val) {
         queryString.append( && ).append(fieldName).append(:[)
                 .append(formatUTCString(val)).append( TO ).append(*]);
     }
 
 
     public void orDateGreaterThan(String fieldName, Date val) {
         queryString.append( || ).append(fieldName).append(:[)
                 .append(formatUTCString(val)).append( TO ).append(*]);
     }
 
 
     public void andDateGreaterThanOrEqualTo(String fieldName, Date val) {
         queryString.append( && ).append(fieldName).append(:[)
                 .append(formatUTCString(val)).append( TO ).append(*]);
     }
 
 
     public void orDateGreaterThanOrEqualTo(String fieldName, Date val) {
         queryString.append( || ).append(fieldName).append(:[)
                 .append(formatUTCString(val)).append( TO ).append(*]);
     }
 
 
     public void andLessThan(String fieldName, String val) {
         queryString.append( && ).append(fieldName).append(:[).append(*)
                 .append( TO ).append(val).append(]);
     }
 
 
     public void orLessThan(String fieldName, String val) {
         queryString.append( && ).append(fieldName).append(:[).append(*)
                 .append( TO ).append(val).append(]);
     }
 
 
     public void andLessThanOrEqualTo(String fieldName, String val) {
         queryString.append( && ).append(fieldName).append(:[).append(*)
                 .append( TO ).append(val).append(]);
     }
 
 
     public void orLessThanOrEqualTo(String fieldName, String val) {
         queryString.append( && ).append(fieldName).append(:[).append(*)
                 .append( TO ).append(val).append(]);
     }
 
 
     public void andDateLessThan(String fieldName, Date val) {
         queryString.append( && ).append(fieldName).append(:[).append(*)
                 .append( TO ).append(formatUTCString(val)).append(]);
     }
 
 
     public void orDateLessThan(String fieldName, Date val) {
         queryString.append( && ).append(fieldName).append(:[).append(*)
                 .append( TO ).append(formatUTCString(val)).append(]);
     }
 
 
     public void andDateLessThanOrEqualTo(String fieldName, Date val) {
         queryString.append( && ).append(fieldName).append(:[).append(*)
                 .append( TO ).append(formatUTCString(val)).append(]);
     }
 
 
     public void orDateLessThanOrEqualTo(String fieldName, Date val) {
         queryString.append( && ).append(fieldName).append(:[).append(*)
                 .append( TO ).append(formatUTCString(val)).append(]);
     }
 
 
     public void andLike(String fieldName, String val) {
         queryString.append( && ).append(fieldName).append(:*).append(val)
                 .append(*);
     }
 
 
     public void orLike(String fieldName, String val) {
         queryString.append( || ).append(fieldName).append(:*).append(val)
                 .append(*);
     }
 
 
     public void andNotLike(String fieldName, String val) {
         queryString.append( && ).append(-).append(fieldName).append(:*)
                 .append(val).append(*);
     }
 
 
     public void orNotLike(String fieldName, String val) {
         queryString.append( || ).append(-).append(fieldName).append(:*)
                 .append(val).append(*);
     }
 
 
     public void andIn(String fieldName, String[] vals) {
         queryString.append( && );
         in(fieldName, vals);
     }
     private void in(String fieldName, String[] vals) {
         List<string> list=Arrays.asList(vals);
         in(queryString,fieldName,list);
     }
     
     public void orIn(String fieldName, List<string> vals) {
         queryString.append( || );
         in(queryString,fieldName,vals);
     }
 
 
     private static void in(StringBuffer queryString,String fieldName, List<string> vals) {
         queryString.append(();
         inStr(queryString, fieldName, vals);
         queryString.append());
     }
 
 
     private static void inStr(StringBuffer queryString, String fieldName,
             List<string> vals) {
         int index = 0 ;
         for (String val : vals) {
             if ( 0 != index) {
                 queryString.append( || );
             }
             queryString.append(fieldName).append(:).append(val);
             index++;
         }
     }
     
     //instead of NOT [condition] use (*:* NOT [condition])
     public void andNotIn(String fieldName, String[] vals) {
         List<string> list=Arrays.asList(vals);
         queryString.append(&&();
         queryString.append(*:* NOT );
         inStr(queryString, fieldName, list);
         queryString.append());
     }
 
 
     public void andDateBetween(String fieldName, Date startDate, Date endDate) {
         queryString.append( && ).append(fieldName).append(:[)
                 .append(formatUTCString(startDate)).append( TO )
                 .append(formatUTCString(endDate)).append(]);
     }
 
 
     public void orDateBetween(String fieldName, Date startDate, Date endDate) {
         queryString.append( || ).append(fieldName).append(:[)
                 .append(formatUTCString(startDate)).append( TO )
                 .append(formatUTCString(endDate)).append(]);
     }
 
 
     public void andDateNotBetween(String fieldName, Date startDate, Date endDate) {
         queryString.append( && ).append(-).append(fieldName).append(:[)
                 .append(formatUTCString(startDate)).append( TO )
                 .append(formatUTCString(endDate)).append(]);
     }
 
 
     public void orDateNotBetween(String fieldName, Date startDate, Date endDate) {
         queryString.append( && ).append(-).append(fieldName).append(:[)
                 .append(formatUTCString(startDate)).append( TO )
                 .append(formatUTCString(endDate)).append(]);
     }
 
 
     public void andBetween(String fieldName, String start, String end) {
         queryString.append( && ).append(fieldName).append(:[).append(start)
                 .append( TO ).append(end).append(]);
     }
 
 
     public void orBetween(String fieldName, String start, String end) {
         queryString.append( || ).append(fieldName).append(:[).append(start)
                 .append( TO ).append(end).append(]);
     }
 
 
     public void andNotBetween(String fieldName, String start, String end) {
         queryString.append( && ).append(-).append(fieldName).append(:[)
                 .append(start).append( TO ).append(end).append(]);
     }
 
 
     public void orNotBetween(String fieldName, String start, String end) {
         queryString.append( || ).append(-).append(fieldName).append(:[)
                 .append(start).append( TO ).append(end).append(]);
     }
 
 
     public void andStartSub() {
         queryString.append( && ();
     }
 
 
     public void orStartSub() {
         queryString.append( || ();
     }
 
 
     public void endSub() {
         queryString.append());
     }
 
 
     private String formatUTCString(Date d) {
         SimpleDateFormat sdf = new SimpleDateFormat(yyyy-MM-dd 'T' HH:mm:ss 'Z' );
         String s = sdf.format(d);
         return s;
     }
 
 
     public int execQueryTotalCount() {
         SolrQuery params = handleQuery();
         params.set(start, 0 );
         params.set(rows, Integer.MAX_VALUE);
         QueryResponse response = null ;
         try {
             response = server.query(params);
             return response.getResults().size();
         } catch (SolrServerException e) {
             logger.error(, e);
         } catch (IOException e) {
             logger.error(, e);
         }
 
 
         return 0 ;
     }
相關文章
相關標籤/搜索