天天看點

全文檢索引擎Solr

Solr采用Lucene搜尋庫為核心,提供全文索引和搜尋開源企業平台,提供REST的HTTP/XML和JSON的API,如果你是Solr新手,那麼就和我一起來入門吧!本教程以solr4.8作為測試環境,jdk版本需要1.7及以上版本。

準備

本文假設你對Java有國中級以上水準,是以不再介紹Java相關環境的配置。下載下傳解壓縮solr,在example目錄有start.jar檔案,啟動:

1

java -jar start.jar

浏覽器通路:http://localhost:8983/solr/,你看到的就是solr的管理界面

索引資料

服務啟動後,目前你看到的界面沒有任何資料,你可以通過POSTing指令向Solr中添加(更新)文檔,删除文檔,在exampledocs目錄包含一些示例檔案,運作指令:

1

java -jar post.jar solr.xml monitor.xml

上面的指令是向solr添加了兩份文檔,打開這兩個檔案看看裡面是什麼内容,solr.xml裡面的内容是:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

<add>

<doc>

<field name=

"id"

>SOLR1000</field>

<field name=

"name"

>Solr, the Enterprise Search Server</field>

<field name=

"manu"

>Apache Software Foundation</field>

<field name=

"cat"

>software</field>

<field name=

"cat"

>search</field>

<field name=

"features"

>Advanced Full-Text Search Capabilities using Lucene</field>

<field name=

"features"

>Optimized

for

High Volume Web Traffic</field>

<field name=

"features"

>Standards Based Open Interfaces - XML and HTTP</field>

<field name=

"features"

>Comprehensive HTML Administration Interfaces</field>

<field name=

"features"

>Scalability - Efficient Replication to other Solr Search Servers</field>

<field name=

"features"

>Flexible and Adaptable with XML configuration and Schema</field>

<field name=

"features"

>Good unicode support: h&#xE9;llo (hello with an accent over the e)</field>

<field name=

"price"

>

</field>

<field name=

"popularity"

>

10

</field>

<field name=

"inStock"

>

true

</field>

<field name=

"incubationdate_dt"

>

2006

-

01

-17T00:

00

:

00

.000Z</field>

</doc>

</add>

表示向索引中添加一個文檔,文檔就是用來搜尋的資料源,現在就可以通過管理界面搜尋關鍵字”solr”,具體步驟是:

全文檢索引擎Solr

點選頁面下的

Execute Query

按鈕後右側就會顯示查詢結果,這個結果就是剛才導入進去的solr.xml的json格式的展示結果。solr支援豐富的查詢文法,比如:現在想搜尋字段

name

裡面的關鍵字”Search”就可以用文法

name:search

,當然如果你搜尋

name:xxx

就沒有傳回結果了,因為文檔中沒有這樣的内容。

資料導入

導入資料到Solr的方式也是多種多樣的:

  • 可以使用DIH(DataImportHandler)從資料庫導入資料
  • 支援CSV檔案導入,是以Excel資料也能輕松導入
  • 支援JSON格式文檔
  • 二進制文檔比如:Word、PDF
  • 還能以程式設計的方式來自定義導入

更新資料

如果同一份文檔solr.xml重複導入會出現什麼情況呢?實際上solr會根據文檔的字段

id

來唯一辨別文檔,如果導入的文檔的

id

已經存在solr中,那麼這份文檔就被最新導入的同

id

的文檔自動替換。你可以自己嘗試試驗一下,觀察替換前後管理界面的幾個參數:

Num Docs

Max Doc

Deleted Docs

的變化。

  • numDocs:目前系統中的文檔數量,它有可能大于xml檔案個數,因為一個xml檔案可能有多個

    <doc>

    标簽。
  • maxDoc:maxDoc有可能比numDocs的值要大,比如重複post同一份檔案後,maxDoc值就增大了。
  • deletedDocs:重複post的檔案會替換掉老的文檔,同時deltedDocs的值也會加1,不過這隻是邏輯上的删除,并沒有真正從索引中移除掉

删除資料

通過id删除指定的文檔,或者通過一個查詢來删除比對的文檔

1 2

java -Ddata=args -jar post.jar

"<delete><id>SOLR1000</id></delete>"

java -Ddata=args -jar post.jar

"<delete><query>name:DDR</query></delete>"

此時

solr.xml

文檔從索引中删除了,再次搜”solr”時不再傳回結果。當然solr也有資料庫中的事務,執行删除指令的時候事務自動送出了,文檔就會立即從索引中删除。你也可以把commit設定為false,手動送出事務。

1

java -Ddata=args  -Dcommit=

false

-jar post.jar

"<delete><id>3007WFP</id></delete>"

執行完上面的指令時文檔并沒有真正删除,還是可以繼續搜尋相關結果,最後可以通過指令:

1

java -jar post.jar -

送出事務,文檔就徹底删除了。現在把剛剛删除的檔案重新導入Solr中來,繼續我們的學習。

删除所有資料:

1

http:

//localhost:8983/solr/collection1/update?stream.body=<delete><query>*:*</query></delete>&commit=true

删除指定資料

1

http:

//localhost:8983/solr/collection1/update?stream.body=<delete><query>title:abc</query></delete>&commit=true

多條件删除

1

http:

//localhost:8983/solr/collection1/update?stream.body=<delete><query>title:abc AND name:zhang</query></delete>&commit=true

查詢資料

查詢資料都是通過HTTP的GET請求擷取的,搜尋關鍵字用參數

q

指定,另外還可以指定很多可選的參數來控制資訊的傳回,例如:用

fl

指定傳回的字段,比如

f1=name

,那麼傳回的資料就隻包括name字段的内容

1

http:

//localhost:8983/solr/collection1/select?q=solr&fl=name&wt=json&indent=true

  • 排序

    Solr提供排序的功能,通過參數

    sort

    來指定,它支援正序、倒序,或者多個字段排序
    • q=video&sort=price desc
    • q=video&sort=price asc
    • q=video&sort=inStock asc, price desc

      預設條件下,Solr根據

      socre

       倒序排列,socre是一條搜尋記錄根據相關度計算出來的一個分數。
  • 高亮

    網頁搜尋中,為了突出搜尋結果,可能會對比對的關鍵字高亮出來,Solr提供了很好的支援,隻要指定參數:

    • hl=true #開啟高亮功能
    • hl.fl=name #指定需要高亮的字段
1

http:

//localhost:8983/solr/collection1/select?q=Search&wt=json&indent=true&hl=true&hl.fl=features

傳回的内容中包含:
           
1 2 3 4 5

"highlighting"

:{

"SOLR1000"

:{

"features"

:[

"Advanced Full-Text <em>Search</em> Capabilities using Lucene"

]

}

}

文本分析

文本字段通過把文本分割成單詞以及運用各種轉換方法(如:小寫轉換、複數移除、詞幹提取)後被索引,schema.xml檔案中定義了字段在索引中,這些字段将作用于其中.

預設情況下搜尋”power-shot”是不能比對”powershot”的,通過修改schema.xml檔案(solr/example/solr/collection1/conf目錄),把features和text字段替換成”text_en_splitting”類型,就能索引到了。

1 2 3

<field name=

"features"

type=

"text_en_splitting"

indexed=

"true"

stored=

"true"

multiValued=

"true"

/>

...

<field name=

"text"

type=

"text_en_splitting"

indexed=

"true"

stored=

"false"

multiValued=

"true"

/>

修改完後重新開機solr,然後重新導入文檔

1

java -jar post.jar *.xml

現在就可以比對了

  • power-shot—>Powershot
  • features:recharing—>Rechargeable
  • 1 gigabyte –> 1G

lucene/solr的缺點

lucene/solr的缺點 solrlucenehadoop  1) http 請求做了cache,有時候會出現新資料不可見,cache滞後的問題。—cache優化下也不是問題

2) admin 背景頁面,支援中文、複雜查詢文法上,欠友好。—自己稍加擴充也不是問題

3) swap core的時候,單結點多core,并且core對應的索引比較大的時候,切換過程出現記憶體2倍化現象,甚至逾時現象。—如果分前後排切換這些都不是問題了。

4) index build和index search往往在一起,導緻全量過程,磁盤峰值3倍化。一份原來的、一份建立的、一份優化的時候。—-當然,build和search分離是可以解決這個問題的,也是正常做法。

5) build 和search在一起,也使得build和search的一些參數設定不能差別對待,尤其是build和search合體的時候,預留磁盤、記憶體等加速build,反而影響search。—-當然可以 build search分離搞定

6) 分布式查詢,如果有merge,性能有些問題。—-當然可以将資料分區,避免merge 7) 得分因子是可以調整的,但是得分因子的增加、得分公式的擴充,無法直接從solr配置插入。—-但是,可以擴充lucene的代碼或者參數spanquery,重新一個query,插入solr,這樣工作量稍大.另外,社群提供了bm25、pagerank等排序batch,對lucene有是以了解後,就可以直接引用了。

8) solr分布式索引全量、增量控制粒度,尚不夠友好。指定結點、任何時刻全量,指定條件下增量都不夠順利。盡管solr提供了自定義擴充實作方法。這些也不是很大問題。

9) solr build和search和在一起,資料和業務其實綁定在一起了,沒有徹底隔離。使得在上100個core的時候,資料源管理維護變得非常消耗資源。直接引入hadoop或者其他nosql存儲時目前最流行的用來隔離資料和業務耦合性了。開源的分布式lucene方案非常多.

10) ABTest 共享相同索引目錄,而不同排序或者不同分詞 solr不能直接支援 11) ABTest 獨立索引目錄,不同排序或者不同分詞,solr也不能直接支援

12) 一個core對應多個子目錄,查詢既可以查指定子目錄也可以全部子目錄查,以及更新某個子目錄索引或者全部子目錄索引,solr也不能直接支援,而這些在大資料量的時候是需要支援這些功能的。

13)solr或者lucene目前不支援快速的“局部”更新。這裡是指對document的某個字段的快速更新,目前是需要傳入完整的document,然後add進去。如果document的不變字段來源多個源的話,IO、計算資源有些浪費,如果更新量不大還好。—當然可以對更新的單獨開辟記憶體來處理,而更大的那個基本索引不去動他。

14)solr不支援第三方條件過濾。例如從倒排中過濾處理一批doc,而這些doc需要與外部源進行doc域值過濾。問題主要是第三方資訊動态性太強,不利于直接寫索引中去。

15)solr 在支援中文分詞的時候,有很多第三方包可以引入,但需要擴充queryparse有時候,總體看有優勢也有劣勢。優勢是引入友善,劣勢是詞庫、算法體系和lucene的不完全相容,擴充、完善不是那麼容易。

16)在排序上,對與去重或者對應基于時間動态性上,還沒有現成的支援。去重是指排序的前幾條結果,可能某個域值完全相同了,或者某幾個域值完全相同,導緻看起來,靠前的結果帶有一些關聯字段的“聚集性”,對有些應用來說,并不是最好的。

在時間因素上動态性,也沒有直接支援,也隻能靠間接的按時間排序來實作。 這個問題其實不是lucene、solr要關注的吧,應該是應用的特殊性導緻的吧。

17) solr、lucene輸出的日志,尚沒有一個通用的分析工具,包括高頻詞、查詢query聚合性等。隻能自行去解析。

18) 在支援推薦上,還不能将log資訊直接關聯起來,推薦也基本上靠離線計算好,導入反向索引,查詢再關聯起來。

19) 當記憶體30個G 以上,單節點索引資料量比較大的時候,jvm環境下FGC和記憶體管理顯得非常辣手。調優需要仔細的測試

20) lucene很少面向接口,solr很多面向接口,插件化、可擴充使得solr很靈活

21)對于垂直型的平台化搜尋,支援N個不同應用、不同schema、不同資料源、不同更新頻率、不同查詢邏輯、不同通路請求量、不同性能名額要求、不同機器配置、垂直擴容、水準擴容,solr顯得不夠勝任,盡管solrcloud中已經有非常多的寶貴設計經驗。

22)流控和數控,solr也不能直接支援。通路請求不支援定時和定量控制,索引垂直擴容(增加索引副本,支撐更多通路請求)、索引水準擴容(增加索引分區數,支撐更多資料量,平衡性能和空間壓力)

23) solr自容錯還不夠強大。例如schema變更導緻的不合理檢測以及配置錯誤的復原、solrconfig的一些參數不能動态擷取,必須事先配置好。oom之後不能自動reload!請求量大的時候也不能抛棄一些請求。

24) 基于位操作的進階應用還不夠靈活,例如boolean 存儲和facet、byte[]存儲和facet、group等,支撐仍然不夠友好。

25) query parse基本沒有預測功能,不能調整query順序和自動收縮條件。當然一般情況下是不需要這麼複雜的優化。

26)一些比較變态的查詢需求不是特别高效。例如查詢某個域不空。當然可以将空域采取預設值代替,查詢預設值再過濾。

27)對于唯一值域,沒有優化,導緻唯一值域的term資料膨脹。最常見的就是更新時間、上傳時間等,占了非常大的term比例。

28)multivalue 字段,實質是建立多個相同域名的字段,并不是一個域。對于域值很多内容的話,隻好和在一起儲存。同時,long int short float double 等數組不能直接作為一個類型儲存,全部得轉為字元存儲。空間和效率有些低。

29)有些詞出現的頻率特别高,導緻該詞的倒排連非常長,solr、lucene也沒有幹涉。任務交給應用自己斟酌,實際上solr單節點對于命中超過100w的,并多字段排序的時候,cache失效時性能非常糟糕的。

30)solr\lucene 對千萬級别應用非常擅長,億級别應用需要慎重對待。

:http://www.chinastor.com/a/dashuju/0G3Y332014.html

http://www.importnew.com/12607.html