歡迎您光臨本站 註冊首頁

Apache Solr的新特性 利用Solr 1.3的新特性和改進

←手機掃碼閱讀     火星人 @ 2014-03-10 , reply:0

摘要:在使用Apache Solr 實現更加靈巧的搜索 系列文章發表之後,Apache Solr 又添加了很多新的特性和性能改進.在本文中,Solr 和 Lucene 的負責人 Grant Ingersoll 詳細介紹了 Solr 1.3 的新改進,包括分散式搜索、輕鬆資料庫導入、集成拼寫檢查和新的擴展API 等等.

Apache Solr 是一個開源的搜索伺服器,主要基於 HTTP 和 Apache Lucene.2007 年,我在一個包含有兩個部分的系列文章 使用 Apache Solr 實現更加靈巧的搜索 中向 developerWorks 讀者介紹了 Solr.由於最近又發布了 Solr 1.3 版本,所有應該詳述一下 Solr 自 2007 年以後的許多新特性和增強功能.

Solr 包含有很多的企業就緒特性,比如輕鬆的配置和管理、多客戶機語言綁定、索引複製、緩存、統計數據以及日誌記錄.Solr 的 1.3 版本以 Apache Lucene 2.3 版本的巨大性能提升為基礎,並增加了一個新的、向後兼容的、即插即用組件架構.該架構使開發人員踴躍創建可以進一步增強 Solr 的組件.例如,1.3 版本就包含能夠實現以下功能的組件:

● 「您是不是要找……」 拼寫檢查
● 查找 「類似的」 Document
● 根據編輯輸入(又稱付費排序)覆蓋搜索結果

另外,查詢解析、搜索、分類以及調試這樣的現有功能也被組件化了.現在,您可以通過組合這些組件來自定義創建 SolrRequestHandler.,Solr 還增加了直接為資料庫內容創建索引的功能,並且通過分散式搜索來支持龐大的系統,這一點對很多企業都很重要.

,我將簡單複習一下 Solr,然後介紹如何獲取和安裝最新版本的 Solr 以及升級早期版本的要點.接著,我會介紹 Solr 1.3 的一些重要的增強功能,再看一下 Solr 的新特性.

複習:Solr 概念

從概念上,Solr 可以被分成四大塊:

● 模式(schema.xml)
● 配置(solrconfig.xml)
● 索引
● 搜索

要理解模式,需要先理解 Lucene 對 Document 的註釋.一個 Document 包含一個或多個 Field.一個 Field 由名稱、內容和給出了內容的處理方法的元數據組成.分析內容可以使其被搜索到.而分析則是通過將一個 Tokenizer 與零個或零個以上的 TokenFilter 鏈接到一起來完成的,Tokenizer 能夠將輸入流拆分為單詞(標記),TokenFilter 能夠改變(例如,詞幹)或移除標記.Solr 模式能夠在沒有代碼的情況下輕鬆配置分析過程.它還提供了更強大的鍵入功能,讓您能夠將 Field 具體指定為 String、int、float 或其他原有的或自定義的類型.

在配置方面,solrconfig.xml 文件不僅指定了 Solr 如何處理索引、突出顯示、分類、搜索以及其他請求,還指定了用於指定緩存的處理方法的屬性,以及用於指定 Lucene 管理索引的方法的屬性.配置取決於模式,但模式不取決於配置.

索引和搜索都是通過向 Solr 伺服器發送請求來實現的.索引的實現方法很簡單,用 POST 一個描述所有 Field 及其內容的 XML 文檔就可以了,如位於 apache-solr-1.3.0/example/exampledocs/ 目錄下的 hd.xml 樣例文檔,如清單 1 所示:

清單 1. 樣例 XML 文檔

<add>
<doc>
<field name="id">SP2514N</field>
<field name="name">Samsung SpinPoint P120 SP2514N -
hard drive - 250 GB - ATA-133</field>
<field name="manu">Samsung Electronics Co. Ltd.</field>
<field name="cat">electronics</field>
<field name="cat">hard drive</field>
<field name="features">7200RPM, 8MB cache, IDE Ultra ATA-133</field>
<field name="features">NoiseGuard, SilentSeek technology, Fluid
Dynamic Bearing (FDB) motor</field>
<field name="price">92</field>
<field name="popularity">6</field>
<field name="inStock">true</field>
</doc>
</add>

要實現搜索則只需要發送 HTTP GET,比如:

http://localhost:8983/solr/select?indent=on&version=2.2&q=ipod&start=0&rows=10
&fl=*,score&qt=standard&wt=standard

在這個例子,查詢 ipod 被提交,它要求 10 個結果.(現在,與 Solr 一起提供的還有一個稱為 SolrJ 的客戶機,它將 HTTP 請求的所有細節信息都隱藏在一組很容易使用的 Java™ 類中.我將在本文 後半部分 介紹 SolrJ).

對於從更大的上下文理解 Solr 設計,這些關於 Solr 概念的快速複習已經足夠.

安裝 Solr 1.3

要使用 Solr 和本文中的樣例,您必須先安裝以下軟體:

● Java 1.5 或更高版本.
● Web 瀏覽器,您將用它查看管理頁面.我使用的是 Firefox,但可以使用其他現代瀏覽器.
● 要運行 DataImportHandler

樣例,需要一個資料庫及其 JDBC 驅動.在本文的樣例中,我使用的是 PostgreSQL;MySQL 或其他資料庫應該也可以,但可能需要修改我編寫的 SQL 以使它適合您的資料庫
● 需要一個 servlet 容器.我在本文中使用的是 Jetty,它與 Solr 打包在一起,也就沒必要使用其他容器了.但如果您偏愛 Tomcat 或其它容器的話,Solr 也能很好地適應它們.

Solr 的新起點

安裝了上述軟體之後,從 Apache Mirrors Web 站點 下載 Solr 1.3.0 版本,並將其解壓縮到特定的目錄下.解壓縮包將創建一個名為 apache-solr-1.3.0 的目錄.然後在一個終端(命令提示符)中完成以下步驟:

1、cd apache-solr-1.3.0/example(在 Windows? 上使用 ).

2、java -jar start.jar.然後等待,直到在日誌輸出中看到如下幾行,它表明伺服器已經啟動:

2008-10-01 09:57:06.336::INFO: Started SocketConnector @ 0.0.0.0:8983
Oct 1, 2008 9:57:06 AM org.apache.solr.core.SolrCore registerSearcher
INFO: [] Registered new searcher Searcher@d642fd main

3、將 Web 瀏覽器轉到 http://localhost:8983/solr,您會看到一個 Solr 歡迎頁面.

4、在另外一個終端中會出現 cd apache-solr-1.3.0/example/exampledocs.

5、java -jar post.jar *.xml.這會自動向 Solr 添加一組文檔.

6、在瀏覽器的管理員頁面上嘗試查詢(http://localhost:8983/solr/admin/form.jsp).

圖 1 顯示了在我的瀏覽器上嘗試查詢 ipod 產生的結果(有刪節):

現在,您的電腦上已經安裝並運行 Solr 1.3,可以工作了.在本文中,我將使用並修改位於 pache-solr-1.3.0/example/solr/conf 目錄中的樣例 solrconfig.xml 和 schema.xml.我先介紹一下與升級到 Solr 1.3 版本有關的一些問題,然後再介紹一下該最新版本中的增強功能.如果不需要升級的話,您可以直接跳到 增強功能 部分.

升級 Solr

Solr 1.3.0 與早期的 Solr 版本是兼容的.但升級時仍有幾件事情需要注意.對於啟動器來說,如果使用 複製 的話,需要升級 worker 節點,然後再升級 master 節點.

Solr 複製Solr 中的複製可能會涉及到一個或多個 worker 節點,它們都運行 Solr,將索引的本地副本與 master 節點上的更改進行同步.複製允許 Solr 進行擴展,以很高的查詢容量來滿足應用程序的需求,不會降低性能.Solr 能夠很有效地處理該過程.

第二,這個版本的 Solr 包含新版本的 Lucene.其實,這就意味著 Solr 將會升級內部的 Lucene 文件格式,也就是說舊版的 Solr 可能無法讀取新的版本.,在升級前先備份索引是明智之舉,避免以後需要降級版本.

第三,Solr 1.3 還包含 Dr. Martin Porter 的新版 Snowball 派生器.如果用它們派生單詞的話,那麼對於過去用某種方法派生的單詞,現在可能(雖然可能性不大)不再使用相同的方法了.最保險的做法是為內容重新創建索引,這樣就避免查詢時間分析和索引分析不匹配.

除了有些用戶可能會遇到的這些問題以外,Solr 1.3 的確應該代替早期的版本.現在您已經準備好學習本文的重用部分:增強 Solr 現有的功能.

增強功能

Solr 1.1 和 1.2 使用起來很方便,但是,和所有最簡單的軟體一樣,它們都留有改進的空間.Solr 1.3 包含有很多對伺服器的穩定性和性能的故障修復功能和改進.

性能增強

,最新的版本將 Lucene 庫升級到了最近的版本,該版本含有很多性能改進.在測試中,我看到索引速度提高了 5 倍,而有些人則聲稱提高了 2 到 8 倍.幸運的是,所有的 Solr 用戶都可以享受到更快的索引,大部分的性能增進都不需要改變配置.

但是,很容易改變 solrconfig.xml 中的一個配置,讓應用程序更好地控制索引期間使用的內存量.在 1.1 和 1.2 版本中,Solr 會在內存中的文檔達到一定數量時將索引的文檔寫到磁碟中,而不管文檔的大小.這經常導致內存不被充分利用,文檔較小時,儘管內存有剩餘,文檔還是被過度刷新;而文檔較大需要更大內存時,又不能及時刷新它.現在,solrconfig.xml 的 <indexDefaults> 部分有了 <ramBufferSizeMB> 選項,您可以指定用於緩衝內存中的文檔的內存量,而不是由文檔的數量來決定.

更多擴展點

在 Solr 1.3 中,擴展 Solr 以及配置和重新整理擴展變得十分簡單.以前,您需要編寫一個 SolrRequestHandler 來實現新功能.這個方法的問題是其他 SolrRequestHandler 很難重用該功能.例如,您可能有更好的分類方法,但卻想保留現有的查詢與突出顯示功能.為了解決這個問題,Solr 項目提出了將各種 SolrRequestHandler(比如 StandardRequestHandler 和 DismaxRequestHandler)重構為組件 — 稱為 SearchComponent — 的想法,這些組件可以鏈接起來,形成一個新的 SolrRequestHandler.現在,您只要關注 SearchComponent 的新功能就可以了,不用再費神思考怎樣才能最好地擴展、重用或複製其他功能.

不過請放心,現有的 SolrRequestHandler 仍然可以像以前一樣無縫地工作,但它們現在僅僅是負責實際工作的圍繞 SearchComponent 的包裝器而已.表 1 介紹了一些新 SearchComponent 的詳細信息.稍後,我還將在本文中提供有關表 1 中的兩個組件的更多信息(MoreLikeThisComponent 和 SpellCheckComponent.參見 參考資料 中的 SearchComponent 鏈接).

表 1. 常用的 SearchComponent

名稱 說明和查詢樣例
QueryComponent 負責將查詢提交到 Lucene 並返回 Document 的列表.

http://localhost:8983/solr/select?&q=iPod&start=0&rows=10
FacetComponent 決定結果集的分類.

http://localhost:8983/solr/select?&q=iPod&start=0&rows=10&facet=true&facet.field=inStock
MoreLikeThisComponent 為每個搜索結果查找與結果類似的文檔,並返回這些結果.

http://localhost:8983/solr/select?&q=iPod&start=0&rows=10&mlt=true&mlt.fl=features&mlt.count=1
HighlightComponent 在搜索結果的正文中突出顯示查詢詞語的位置.

http://localhost:8983/solr/select?&q=iPod&start=0&rows=10&hl=true&hl.fl=name
DebugComponent 返回有關查詢的解析方式的信息,以及每個文檔的記錄方式的詳細信息.

http://localhost:8983/solr/select?&q=iPod&start=0&rows=10&debugQuery=true
SpellCheckComponent 根據索引的內容對輸入查詢進行拼寫檢查,並提供其他備選方法.


http://localhost:8983/solr/spellCheckCompRH?&q=iPood&start=0&rows=10&spellcheck=true&spellcheck.build=true

默認情況下,所有 SolrRequestHandler 都附帶有 QueryComponent、FacetComponent、MoreLikeThisComponent、HighlightComponent 和 DebugComponent.要添加自己的組件,您需要:

1、擴展 SearchComponent 類.
2、使 Solr 可以使用這些代碼(參見 參考資料 中鏈接到 Solr Plugins wiki 頁面的鏈接).
3、在 solrconfig.xml 中配置它.

例如,假定我創建了一個名為 com.grantingersoll.MyGreatComponent 的 SearchComponent,並讓 Solr 可以使用它,而現在我想要將其插入到 SolrRequestHandler 中以查詢它.那麼我需要聲明該組件,如清單 2 所示,這樣 Solr 才能知道如何實例化這個類:

清單 2. 組件聲明

<searchComponent name="myGreatComp" class="com.grantingersoll.MyGreatComponent"/>

接下來,我需要告知 Solr 要將其連接到哪個 SolrRequestHandler.在這個用例中,我可以使用三個選擇之一:

顯式地聲明所有 SearchComponent,如清單 3 所示:

清單 3. 顯式地聲明所有 SearchComponent

<requestHandler name="/greatHandler" class="solr.SearchHandler">
<arr name="components">
<str>query</str>
<str>facet</str>
<str>myGreatComp</str>
<str>highlight</str>
<str>debug</str>
</arr>
</requestHandler>

預先將組件添加到現有的鏈接上,如清單 4 所示:

清單 4. 預先將組件添加到現有的鏈接上

<requestHandler name="/greatHandler" class="solr.SearchHandler">
<arr name="first-components">
<str>myGreatComp</str>
</arr>
</requestHandler>

將組件追加到現有鏈接上,如清單 5 所示:

清單 5. 將組件追加到現有鏈接上

<requestHandler name="/greatHandler" class="solr.SearchHandler">
<arr name="last-components">
<str>myGreatComp</str>
</arr>
</requestHandler>

現在,與 SearchComponent 重構類似,也可以將查詢解析和 SolrRequestHandler 分開.因此,您可以把 DismaxQParser 與任何 SolrRequestHandler 一起使用.您可以通過輸入 defType 參數來實現.例如:

http://localhost:8983/solr/select?&q=iPod&start=0&rows=10&defType=dismax&qf=name

使用 Dismax 查詢解析器來解析查詢,而不是標準 Lucene 查詢解析器.

另外,您也可以通過擴展 QParser 和 QParserPlugin 來創建您自己的查詢解析器,並讓 Solr 可以使用它們,然後在 solrconfig.xml 中配置它.例如,如果我創建了 com.grantingersoll.MyGreatQParser 和 com.grantingersoll.MyGreatQParserPlugin,並使讓 Solr 可以使用它們,那麼我應該在 solrconfig.xml 中按以下方式配置它們:

<queryParser name="greatParser" class="com.grantingersoll.MyGreatQParserPlugin"/>

隨後,我可以將 defType=greatParser 鍵/值對添加到一個查詢請求中,以查詢這個新的解析器.

Solr 最近版本還包含了很多其他的改進.如果您有興趣學習更多內容的話,可以看一下 參考資料 中的發布說明鏈接.從這裡開始我們將學習 Solr 的新特性.

新特性

Solr 1.3 擁有很多功能強大的特性,這使它充滿了吸引力.本文剩餘的部分將介紹新 Solr 特性,以及將它們合併到您的應用程序中的方法.為了展示這些內容,我將構建一個簡單的應用程序,它將 RSS 提要和該提要的評級結合起來.評級將儲存在一個資料庫中,RSS 提要來自我的 Lucene 博客的 RSS 提要.完成這個簡單的設置后???我將展示如何使用:

● DataImportHandler
● MoreLikeThisComponent
● QueryElevationComponent (我稱之為 「編輯結果排序」)
● SolrJ
● 分散式搜索(不帶有設置細節信息的架構討論)

如果要實踐這個示例,請 下載樣例應用程序,並按以下說明進行操作:

1、將 sample.zip 拷貝到 apache-solr-1.3.0/example/ 目錄.

2、解壓縮 sample.zip.

3、啟動(或重啟動)Solr:java -Dsolr.solr.home=solr-dw -jar start.jar.

4、以資料庫管理員的身份創建一個名為 solr_dw 的資料庫用戶.具體做法請參看資料庫說明.在 PostgreSQL 中,我的創建方法為:create user solr_dw;.

5、為上述用戶創建一個名為 solr_dw 的資料庫:create database solr_dw with OWNER = solr_dw;.

6、在命令行上執行 src/sql/create.sql 語句:psql -U solr_dw -f create.sql solr_dw.我的輸出為:

gsi@localhost>psql -U solr_dw -f create.sql solr_dw
psql:create.sql:1: ERROR: table "feeds" does not exist
psql:create.sql:2: NOTICE: CREATE TABLE / PRIMARY KEY will create
implicit index "feeds_pkey" for table "feeds"
CREATE TABLE
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1

從資料庫和其他數據源導入數據

在這個結構化數據和非結構化數據的數量都很龐大的年代,經常需要從資料庫、XML/HTML 文件或其他數據源導入數據,並使數據可搜索.過去,要編寫自定義代碼才能創建到資料庫、文件系統或 RSS 提要的自定義連接.但現在,Solr 的 DataImportHandler(DIH)填補了這個空白,它使您能夠從資料庫(通過 JDBC)、RSS 提要、Web 頁面和文件中導入數據.DIH 位於 apache-1.3.0/contrib/dataimporthandler 中,是 apache-1.3.0/dist/apache-solr-dataimporthandler-1.3.0.jar 中的一個 JAR 文件.

DataImportHandler 警告

DataImportHandler 不是文件/Web 爬行器(crawler),它不直接支持從二進位文件格式中提取內容,比如 MS Office、Adobe PDF 或其他專有格式.

在概念上,DIH 可以分解為幾個簡單的部分:

DataSource:獲取內容的資料庫、Web 頁面、RSS 提要或 XML 文件.
● 文檔/實體聲明:指定 DataSource 的內容與 Solr 模式之間的映射.
● 導入:Solr 命令,使用它既可以進行完全導入,也可以只導入已經更改的實體的增量導入.
EntityProcessor:用於映射的代碼.Solr 自帶四個工具:
FileListEntityProcessor:在目錄上迭代並導入文件
SqlEntityProcessor:連接到一個資料庫並導入記錄.
CachedSqlEntityProcessor:將緩存添加到 SqlEntityProcessor.
XPathEntityProcessor:使用 XPath 語句從 XML 文件抽取內容.
Transformer:用戶定義的、可選的代碼,用於在添加到 Solr 之前轉換導入的內容.例如,DateFormatTransformer 能夠標準化日期.
● 變數替代:用運行時的值替代佔位符變數.

,我需要設置一個 SolrRequestHandler 將 DIH 和 Solr 關聯起來.該設置要在 solr-dw/rss/conf/solrconfig.xml 文件中進行,如清單 6 所示:

清單 6. 將 DIH 和 Solr 關聯起來

<requestHandler name="/dataimport"
class="org.apache.solr.handler.dataimport.DataImportHandler">
<lst name="defaults">
<str name="config">rss-data-config.xml</str>
</lst>
</requestHandler>

該配置表明:我可以通過 http://localhost:8983/solr/rss/dataimport 找到 DataImportHandler 實例;該實例必須使用一個名為 rss-data-config.xml 的配置文件(位於 solr_dw/rss/conf 目錄)來獲取它的設置信息.到目前為止,一切都相當簡單.

撥開下一層面紗,rss-data-config.xml 文件就是聲明和使用 DataSource 、實體和 Transformer 的地方.在這個例子中,遇到的 XML 標記(在根元素後面)為 DataSource 聲明,如清單 7 所示:

清單 7. DataSource 聲明

<dataSource name="ratings" driver="org.postgresql.Driver"
url="jdbc:postgresql://localhost:5432/solr_dw" user="solr_dw" />
<dataSource name="rss" type="HttpDataSource" encoding="UTF-8"/>

清單 7 中的第一個聲明設置一個與我的資料庫相連接的 DataSource.它被命名為 ratings,我的評級信息就儲存在裡面.注意,雖然我沒有為資料庫用戶設置密碼,但實際可以向標記添加密碼屬性.如果了解 JDBC 設置的話,那麼就應該很熟悉這個 DataSource 聲明了.第二個 DataSource 名為 rss,它聲明內容將要通過 HTTP 來獲取.稍後將聲明這個 DataSource 的 URL.

下一個值得討論的標記是 <entity> 標記.它用來指定如何將 RSS 提要和資料庫的內容映射到 Solr Document.一個實體就是被索引為一個單一文檔的內容單位.例如,在一個資料庫中,實體聲明規定了如何將每一行轉換成 Document 中的 Field.一個實體里又可以包含一個或多個實體,因此子實體就變成整體 Document 的 Field 結構.

至此,來自 rss-data-config.xml 的帶註釋的示例可以清楚地說明與實體相關的大部分信息.在這個例子中,主實體從一個 RSS 提要獲取內容,並將其與資料庫中的行相關聯以獲得評級.清單 8 是一個縮略的 RSS 提要示例:

清單 8. 縮略的 RSS 反提要

<rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
>
<channel>
<title>Grant's Grunts: Lucene Edition</title>
<link>http://lucene.grantingersoll.com</link>
<description>Thoughts on Apache Lucene, Mahout,
Solr, Tika and Nutch</description>
<pubDate>Wed, 01 Oct 2008 12:36:02 0000</pubDate>
<item>
<title>Charlotte JUG >> OCT 15TH - 6PM -
Search and Text Analysis</title>
<link>http://lucene.grantingersoll.com/2008/10/01/
charlotte-jug-»-oct-15th-6pm-search-and-text-analysis/</link>
<pubDate>Wed, 01 Oct 2008 12:36:02 0000</pubDate>
<category><![CDATA[Lucene]]></category>
<category><![CDATA[Solr]]></category>
<guid isPermaLink="false">http://lucene.grantingersoll.com/?p=112</guid>
<description><![CDATA[Charlotte JUG >> OCT 15TH - 6PM - Search and Text Analysis
I will be speaking at the Charlotte Java Users Group on Oct. 15th, covering things
like Lucene, Solr, OpenNLP and Mahout, amongst other things.
]]></description>
</item>
</channel>

與此同時,資料庫中的一行包含提要中的文章的 URL、一個評級(我隨便編的)和一個修改日期.現在,我只需將它映射到 Solr 就可以了.為了完成此工作,我將逐行解釋 rss-data-config.xml 中的實體聲明,如清單 9 所示(它包含行數和換行符,以獲得良好的格式):

清單 9. 實體聲明

1. <entity name="solrFeed"
2.pk="link"
3.url="http://lucene.grantingersoll.com/category/solr/feed"
4.processor="XPathEntityProcessor"
5.forEach="/rss/channel | /rss/channel/item"
6. dataSource="rss"
7. transformer="DateFormatTransformer">
8. <field column="source" xpath="/rss/channel/title"
commonField="true" />
9. <field column="source-link" xpath="/rss/channel/link"
commonField="true" />
10. <field column="title" xpath="/rss/channel/item/title" />
11. <field column="link" xpath="/rss/channel/item/link" />
12. <field column="description"
xpath="/rss/channel/item/description" />
13. <field column="category" xpath="/rss/channel/item/category" />
14. <field column="content" xpath="/rss/channel/item/content" />
15. <field column="date" xpath="/rss/channel/item/pubDate"
dateTimeFormat="EEE, dd MMM yyyy HH:mm:ss Z" />
16. <entity name="rating" pk="feed"
query="select rating from feeds where feed = '${solrFeed.link}'"
17. deltaQuery="select rating from feeds where feed = '${solrFeed.link}'
AND last_modified > '${dataimporter.last_index_time}'"
18. dataSource="ratings"
19. >
20. <field column="rating" name="rating"/>
21. </entity>
22. </entity>

第 1 行:實體名(solrFeed).
第 2 行:該項的可選主鍵,只有在導入增量時才用得到.
第 3 行:將要獲取的 URL — 在這個用例中是我在 Solr 上的博客站點.
第 4 行:用於從原始源映射內容的 EntityProcessor.
第 5 行:用於指定如何從 XML 獲取記錄的 XPath 表達.(XPath 提供一種在 XML 文件中指定特定元素或屬性的方法.如果不熟悉 XPath 表達的話,請參閱 參考資料).
第 6 行:要使用的 DataSource 的名稱.
第 7 行:用於將字元串解析成 java.util.Date 的 DateFormatTransformer.


第 8 行:將通道名稱(博客名稱)映射到以 Solr 模式欄位命名的數據源.此過程每個通道只發生一次,因此 commonField 屬性指定該值必須用於每一個數據項.
第 9-14 行:將 RSS 提要的其他部分映射到 Solr Field.
第 15 行:映射出版日期,但使用 DateFormatTransformer 將值解析為一個 java.util.Date 對象.
第 16-21 行:從資料庫獲取每一篇文章的評級的子實體.
第 16 行:query 屬性指定要運行的 SQL.${solrFeed.link} 值被代替變數解析為每一篇文章的 URL.
第 17 行:導入增量時要運行的查詢.${dataimporter.last_index_time} 由 DIH 提供.
第 18 行:使用 JDBC DataSource.
第 20 行:將資料庫中的評級欄映射到評級欄位.如果未指定名稱屬性,將默認使用欄名.
下一步是運行導入.這可以通過提交 HTTP 請求來實現:
http://localhost:8983/solr/rss/dataimport?command=full-import

該請求先將所有的文檔從索引中移除,然後再進行完全導入.再強調一遍,這個請求從索引中移除全部文檔,一定要警惕這一點.您可以隨時瀏覽 http://localhost:8983/solr/rss/dataimport 獲取 DIH 的狀態.在這個用例中,我的輸出如清單 10 所示:

清單 10. 導入結果

<response>
<lst name="responseHeader">
<int name="status">0</int>
<int name="QTime">0</int>
</lst>
<lst name="initArgs">
<lst name="defaults">
<str name="config">rss-data-config.xml</str>
</lst>
</lst>
<str name="status">idle</str>
<str name="importResponse"/>
<lst name="statusMessages">
<str name="Total Requests made to DataSource">11</str>
<str name="Total Rows Fetched">13</str>
<str name="Total Documents Skipped">0</str>
<str name="Full Dump Started">2008-10-03 10:51:07</str>
<str name="">Indexing completed. Added/Updated: 10 documents.
Deleted 0 documents.</str>
<str name="Committed">2008-10-03 10:51:18</str>
<str name="Optimized">2008-10-03 10:51:18</str>
<str name="Time taken ">0:0:11.50</str>
</lst>
<str name="WARNING">This response format is experimental. It is
likely to change in the future.</str>
</response>

您為其創建索引的文檔的數量可能與我不同(我有可能會把其他 Solr 文章添加到提要).為文檔創建索引之後,我就可以查詢索引了,就像在 http://localhost:8983/solr/rss/select/?q=*:*&version=2.2&start=0&rows=10&indent=on 中一樣,它返回了帶索引的全部文檔,共 10 篇.

有了這些準備,您就可以使用 DIH 了.再深入一些,就是如何替換變數和如何編寫 Transformer 了.要想學習更多有關此話題的知識,請參見 參考資料 中的 DataImportHandler wiki 頁面鏈接.下面將介紹:如何使用 MoreLikeThisComponent 查找相似頁面.

增量導入功能

使用資料庫時,在完全導入之後,下一次只需導入那些改變了的記錄.這個功能就叫做增量導入.不幸的是,它還不能適用於 RSS 提要.要是可以的話,命令應該是這樣的:
http://localhost:8983/solr/rss/dataimport?command=delta-import.

查找相似頁面

MoreLikeThisComponent 和 Solr 模式

MLT 要求欄位被儲存或使用檢索詞向量,檢索詞向量以一種以文檔為中心的方式儲存信息.MLT 通過文檔的內容來計算文檔中關鍵詞語,然後使用原始查詢詞語和這些新詞語創建一個新的查詢.提交新查詢就會返回其他查詢結果.所有這些都可以用檢索詞向量來完成:只需將 termVectors="true" 添加到 schema.xml 中的 <field> 聲明.

在 Google 上嘗試一個查詢,您會注意到每一個結果都包含一個 「相似頁面」 鏈接,單擊該鏈接,就會發布另一個搜索請求,查找出與起初結果類似的文檔.Solr 使用 MoreLikeThisComponent(MLT)和 MoreLikeThisHandler 實現了一樣的功能.如上所述,MLT 是與標準 SolrRequestHandler 集成在一起的;MoreLikeThisHandler 與 MLT 結合在一起,並添加了一些其他選項,但它要求發布一個單一的請求.我將著重講述 MLT,使用它的可能性更大一些.幸運的是,不需要任何設置就可以查詢它,您現在就可以開始查詢.

您可以向請求添加很多 HTTP 查詢參數,並且大部分參數都有智能的默認值,因此我將著重講述使用 MLT 必須了解的參數.

表 2. MoreLikeThisComponent 參數

參數 說明 值域
mlt 在查詢時,打開/關閉 MoreLikeThisComponent 的布爾值. 真|假
mlt.count 可選.每一個結果要檢索的相似文檔數. > 0
mlt.fl 用於創建 MLT 查詢的欄位. 模式中任何被儲存的或含有檢索詞向量的欄位.
mlt.maxqt 可選.查詢詞語的最大數量.由於長文檔可能會有很多關鍵詞語,這樣 MLT 查詢可能會很大,從而導致反應緩慢或可怕的 TooManyClausesException,該參數只保留最關鍵的詞語. > 0

嘗試下面的樣例查詢,然後檢查返回結果中的 moreLikeThis 部分:

http://localhost:8983/solr/rss/select/?q=*:*&start=0&rows=10&mlt=true
&mlt.fl=description&mlt.count=3


http://localhost:8983/solr/rss/select/?q=solr&version=2.2&start=0&rows=10
&indent=on&mlt=true&mlt.fl=description&mlt.fl=title&mlt.count=3

接下來,我將介紹如何嚮應用程序添加 「您是不是要找……」(拼寫檢查).

提供拼寫建議

Lucene 和 Solr 很久以前就開始提供拼寫檢查功能了,但直到添加了 SearchComponent 架構之後,這些功能才可以無縫使用.現在您可以輸入一個查詢,讓它不僅返回查詢結果,並且為查詢詞語提供拼寫建議(如果存在的話).然後可以利用這些建議像 Google 那樣顯示 「您是不是要找……」,或者像 Yahoo! 那樣顯示 「請嘗試……」.

集成拼寫檢查的妙處在於它能夠(必須)根據索引中的標記給出建議.也就是說,它不必根據詞典給出正確拼寫的詞語,而是根據與查詢詞語相似的拼寫給出拼寫建議(包括錯誤拼寫).例如,假設很多很多的人都將單詞 hockey 錯誤拼寫成 hockei.查詢 hockey 的用戶很可能是想查找裡面帶有單詞 hockei 的文檔,它們是相關的(儘管是這些文檔的作者不會拼寫).

SpellCheckComponent 與 MLT 不同,它不需要在 solrconfig.xml 和 schema.xml 文件中進行配置.,模式必須先聲明一個 Field 和一個相關聯的、其內容能夠發揮拼寫詞典的作用的 FieldType.按常規,該 FieldType 的分析過程要保持簡單,不要派生詞語或修改其他標誌.我的樣例 FieldType 聲明了它的 <analyzer>,如清單 11 所示:

清單 11. 聲明一個 <analyzer>

<fieldType name="textSpell" class="solr.TextField" positionIncrementGap="100" >
<analyzer>
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
</analyzer>
</fieldType>

該 <analyzer> 負責基本的標誌化(尤其是拆分空格),然後將標誌變成小寫並移除複製.不用派生詞語,也不用擴展同義詞.就是這麼簡單.接下來我在 schema.xml 文件中聲明了一個 field,名為 spell,它使用 textSpell <fieldType>.接著,我聲明了 <searchComponent>,將 solrconfig.xml 文件中的必要的部分連接起來,如清單 12 所示:

清單 12. 聲明 <searchComponent>

<searchComponent name="spellcheck" class="solr.SpellCheckComponent">
<str name="queryAnalyzerFieldType">textSpell</str>
<lst name="spellchecker">
<str name="name">default</str>
<str name="field">spell</str>
<str name="spellcheckIndexDir">./spellcheckerDefault</str>
</lst>
</searchComponent>

在這個例子中,我將前面聲明的 textSpell <fieldType> 和 queryAnalyzerFieldType 關聯起來.(注意,我使用前面講述的 last-components 技術將組件到 Dismax 和 solrconfig.xml 中的標準 SolrRequestHandler 聲明).這能夠確保正確分析輸入查詢,從而與拼寫索引進行比較.其餘的配置選項指定拼寫檢查器的名稱、包含構建拼寫索引所用的內容的 Field,以及索引在磁碟上的儲存位置.

完成全部配置之後,您必須構建拼寫索引.這可以通過用 HTTP 向組件發送請求來完成,比如:

http://localhost:8983/solr/rss/select/?q=foo&spellcheck=true&spellcheck.build=true

構建了索引之後,像往常一樣查詢並添加 spellcheck=true 參數就會返回建議了.例如,清單 13 打開了拼寫檢查特性:

拼寫檢查構建工作流程

要查詢拼寫檢查索引,必須先構建它.初始構建完成後,您需要確定(通過您的應用程序)重新構建索引的頻率.您也可以在用 solrconfig.xml 中的 postCommit 事件JianTingQi完成提交之後再重新構建它.重構建的頻率一定要以索引的更改數量為基準,但這一點並不是很重要,初始索引創建之後,很大地改動詞典的可能性不大.

清單 13. 顯示拼寫檢查的查詢

http://localhost:8983/solr/rss/select/?q=holr&spellcheck=true

運行清單 13 中的查詢會返回零個結果,但是它會提供以下建議:

<lst name="spellcheck">
<lst name="suggestions">
<lst name="holr">
<int name="numFound">1</int>
<int name="startOffset">0</int>


<int name="endOffset">4</int>
<arr name="suggestion">
<str>solr</str>
</arr>
</lst>
</lst>
</lst>

再深入一步,多個詞語的查詢也可以使用拼寫檢查.組件甚至能夠自動地創建一個推薦的新查詢,該查詢將所有詞語的最佳建議結合起來.這可以通過添加 spellcheck.collate=true 參數來實現.就像在錯誤拼寫查詢中一樣,

http://localhost:8983/solr/rss/select/?q=holr foo&spellcheck=true&indent=on
&spellcheck.collate=true

它生成了作為建議的一部分的結果 <str name="collation">solr for</str>.但是要注意,這個合併的結果可能不會返回結果,這取決於您是否用 AND 將查詢詞語連接起來.

另外,拼寫檢查器還能採用與返回的建議數量和結果質量有關的查詢參數.要想更多地了解 SpellCheckComponent 的詳細信息,請參見 參考資料 中的 Solr wiki 頁面鏈接.

接下來,我將介紹如何用 「付費排序」 來覆蓋結果的自然排序.

編輯結果排序

在理想的情況下,搜索引擎只返回與用戶查詢相關的文檔.而在現實的查詢中,編輯(沒發現更合適的表達)通常需要指定特定文檔在搜索結果中的特定位置.這樣做有很多原因.或許 「置頂」 的文檔就是最好的查詢結果.也可能是公司想讓客戶從相似的選擇中找到利潤率較高的產品.還可能是由第三方付費,提高某些查詢詞語的排名.不管是什麼原因,對於一般的查詢,要根據相關度來排名,讓特定的文檔出現在特定的位置,通常是很困難的(甚至是不可能的).,即便搜索引擎能為某個查詢達到這個目的,它也很可能會在這個過程中破壞其他 50 個查詢.因此,現實中的搜索有這樣一條基本規則:用戶輸入查詢並不等於您必須搜索索引並給文檔評級.我知道,以構建搜索引擎為生的人說這件事有點奇怪,但這是事實.您可以緩存普通的查詢,或只查找結果(Solr 可以完成),或根據上述的某個原因 「硬編碼」 結果.

Solr 使用一個神秘命名的 SearchComponent(即 QueryElevationComponent)實現了簡單排名.為了在樣例應用程序中配置它,我按清單 14 所示的方法聲明它:

清單 14. 聲明一個 QueryElevationComponent

<searchComponent name="elevator"
class="org.apache.solr.handler.component.QueryElevationComponent"
>
<!-- pick a fieldType to analyze queries -->
<str name="queryFieldType">string</str>
<str name="config-file">elevate.xml</str>
</searchComponent>

queryFieldType 屬性指定如何將傳入的查詢與要提升的查詢相匹配.為簡單起見,string FieldType 意味著查詢必須是一個精確匹配的字元串,在 string FieldType 上是不會執行任何分析的.config-file 屬性指定包含查詢和相關聯的結果的文件.它儲存在一個單獨的文件中,這樣才能夠從外部編輯它.文件必須位於 Solr 配置目錄中或 Solr 數據目錄中.如果它不在數據目錄中,那麼它會在 Solr 需要重新裝載索引時再載入.

樣例應用程序將 elevate.xml 儲存在配置目錄中.在它的內部,我為查詢 「Charlotte」 添加了一個條目,以及其他 3 個條目,如清單 15 所示:

清單 15. 樣例 elevate.xml 配置

<query text="Solr">
<doc
id="http://lucene.grantingersoll.com/2008/06/21/solr-spell-checking-addition/"/>
<doc
<!-- Line break is for formatting purposes -->
id="http://lucene.grantingersoll.com/2008/10/01/
charlotte-jug-»-oct-15th-6pm-search-and-text-analysis/"
/>
<doc
id="http://lucene.grantingersoll.com/2008/08/27/solr-logo-contest/" exclude="true"/>
</query>

清單 15 表明第一個鏈接出現的位置應該高於第二個鏈接,而第三個鏈接必須排除在結果之外.此後的結果按正常的順序排列.想要查看正常的結果(包含這個組件時,默認打開提升),運行以下查詢:

http://localhost:8983/solr/rss/select/?q=Solr&version=2.2&start=0&rows=10&indent=on
&fl=link&enableElevation=false

想要查看提升打開時的結果,請嘗試:

http://localhost:8983/solr/rss/select/?q=Solr&version=2.2&start=0&rows=10&indent=on
&fl=link&enableElevation=true

應該會看到插入的提升輸出.

這就是編輯排序.現在您已經能夠輕鬆地為搜索改變查詢結果,不會損害其他結果的質量.

SolrJ

在系列文章 使用 Apache Solr 實現更加靈巧的搜索 中,我借用了一個簡單的客戶機,它通過 Java 平台使用 Apache HTTPClient 與 Solr 通信.現在,在 1.3 版本中,Solr 提供了一個易於使用的、基於 Java 的 API,它避免了 HTTP 鏈接和 XML 命令的所有弊端.這個稱為 SolrJ 的新客戶機是的通過 Java 代碼處理 Solr 更加輕鬆.SolrJ API 通過良好定義的方法調用簡化了索引創建、搜索、排序和分類.

同樣,簡單的例子或許是最好的老師.樣例下載 包含一個名為 SolrJExample.java 的 Java 文件.(參見下載中的 README.txt,查看有關編譯的說明).它展示了如何為 Solr 創建一些文檔的索引,然後再運行一個對結果進行分類的查詢.它做的第一件事是建立一個到 Solr 實例的連接,就像在 SolrServer server = new CommonsHttpSolrServer("http://localhost:8983/solr/rss"); 中一樣.這會創建一個 SolrServer 實例,該實例通過 HTTP 和 Solr 通信.接下來,我將創建一個 SolrInputDocument,用它將要創建索引的內容打包起來,如清單 16 所示:

清單 16. 使用 SolrJ 創建索引

Collection<SolrInputDocument> docs = new HashSet<SolrInputDocument>();
for (int i = 0; i < 10; i ) {
SolrInputDocument doc = new SolrInputDocument();
doc.addField("link", "http://non-existent-url.foo/" i ".html");
doc.addField("source", "Blog #" i);
doc.addField("source-link", "http://non-existent-url.foo/index.html");
doc.addField("subject", "Subject: " i);
doc.addField("title", "Title: " i);
doc.addField("content", "This is the " i "(th|nd|rd) piece of content.");
doc.addField("category", CATEGORIES[rand.nextInt(CATEGORIES.length)]);
doc.addField("rating", i);
//System.out.println("Doc[" i "] is " doc);
docs.add(doc);
}

清單 16 中的循環只是創建了 SolrInputDocument(實際是一個誇張的 Map),然後給它添加 Field.我將它添加到了一個集合中,這樣一次就能將所有的文檔發送到 Solr.藉助這個功能可以極大地加索引的創??,並減少通過 HTTP 發送請求導致的開銷.然後我調用了 UpdateResponse response = server.add(docs);,它負責序列化文檔並將其提交到 Solr.UpdateResponse 返回的值包含處理文檔所用的時間的信息.為了讓這些文檔能夠被搜索到,我又發出一個提交命令:server.commit();.

當然,創建索引之後必須查詢伺服器,如清單 17 帶註釋的代碼所示:

清單 17. 查詢伺服器

//create the query
SolrQuery query = new SolrQuery("content:piece");
//indicate we want facets
query.setFacet(true);
//indicate what field to facet on
query.addFacetField("category");
//we only want facets that have at least one entry
query.setFacetMinCount(1);
//run the query
QueryResponse results = server.query(query);
System.out.println("Query Results: " results);
//print out the facets
List<FacetField> facets = results.getFacetFields();
for (FacetField facet : facets) {
System.out.println("Facet:" facet);
}

在這個簡單的查詢例子中,我設置了一個帶有 content:piece 請求的 SolrQuery 實例.接下來,我表明自己對至少一個條目的所有的分類的分類信息感興趣.,我通過 server.query(query) 調用提交查詢,然後把一些結果列印了出來.這的確是一個過於簡單的例子,但是它展示使用 Solr 時常見的任務,因此使您想到可以實現什麼功能(突出顯示、排序等).


[火星人 ] Apache Solr的新特性 利用Solr 1.3的新特性和改進已經有768次圍觀

http://coctec.com/docs/java/show-post-61963.html