全文檢索引擎Solr系列——入門篇

Solr採用Lucene搜索庫爲核心,提供全文索引和搜索開源企業平臺,提供REST的HTTP/XML和JSON的API,若是你是Solr新手,那麼就和我一塊兒來入門吧!本教程以solr4.8做爲測試環境,jdk版本須要1.7及以上版本。 java

準備

本文假設你對Java有初中級以上水平,所以再也不介紹Java相關環境的配置。下載解壓縮solr,在example目錄有start.jar文件,啓動: python

1
java -jar start.jar

瀏覽器訪問:http://localhost:8983/solr/,你看到的就是solr的管理界面 mysql

索引數據

服務啓動後,目前你看到的界面沒有任何數據,你能夠經過POSTing命令向Solr中添加(更新)文檔,刪除文檔,在exampledocs目錄包含一些示例文件,運行命令: git

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

上面的命令是向solr添加了兩份文檔,打開這兩個文件看看裏面是什麼內容,solr.xml裏面的內容是: github

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">OptimizedforHigh 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">0</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 web

點擊頁面下的Execute Query按鈕後右側就會顯示查詢結果,這個結果就是剛纔導入進去的solr.xml的json格式的展現結果。solr支持豐富的查詢語法,好比:如今想搜索字段name裏面的關鍵字」Search」就能夠用語法name:search,固然若是你搜索name:xxx就沒有返回結果了,由於文檔中沒有這樣的內容。 算法

數據導入

導入數據到Solr的方式也是多種多樣的: sql

  • 可使用DIH(DataImportHandler)從數據庫導入數據
  • 支持CSV文件導入,所以Excel數據也能輕鬆導入
  • 支持JSON格式文檔
  • 二進制文檔好比:Word、PDF
  • 還能以編程的方式來自定義導入

更新數據

若是同一份文檔solr.xml重複導入會出現什麼狀況呢?實際上solr會根據文檔的字段id來惟一標識文檔,若是導入的文檔的id已經存在solr中,那麼這份文檔就被最新導入的同id的文檔自動替換。你能夠本身嘗試試驗一下,觀察替換先後管理界面的幾個參數:Num Docs,Max Doc,Deleted Docs的變化。 mongodb

  • 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


場景:小時候咱們都使用過新華字典,媽媽叫你翻開第38頁,找到「坑爹」所在的位置,此時你會怎麼查呢?毫無疑問,你的眼睛會從38頁的第一個字開始從頭到尾地掃描,直到找到「坑爹」二字爲止。這種搜索方法叫作順序掃描法。對於少許的數據,使用順序掃描是夠用的。可是媽媽叫你查出坑爹的「坑」字在哪一頁時,你要是從第一頁的第一個字逐個的掃描下去,那你真的是被坑了。此時你就須要用到索引。索引記錄了「坑」字在哪一頁,你只需在索引中找到「坑」字,而後找到對應的頁碼,答案就出來了。由於在索引中查找「坑」字是很是快的,由於你知道它的偏旁,所以也就可迅速定位到這個字。

那麼新華字典的目錄(索引表)是怎麼編寫而成的呢?首先對於新華字典這本書來講,除去目錄後,這本書就是一堆沒有結構的數據集。可是聰明的人類善於思考總結,發現每一個字都會對應到一個頁碼,好比「坑」字就在第38頁,「爹」字在第90頁。因而他們就從中提取這些信息,構形成一個有結構的數據。相似數據庫中的表結構:

word    page_no
---------------
坑        38
爹        90
...       ...

這樣就造成了一個完整的目錄(索引庫),查找的時候就很是方便了。對於全文檢索也是相似的原理,它能夠歸結爲兩個過程:1.索引建立(Indexing)2. 搜索索引(Search)。那麼索引究竟是如何建立的呢?索引裏面存放的又是什麼東西呢?搜索的的時候又是如何去查找索引的呢?帶着這一系列問題繼續往下看。

索引

Solr/Lucene採用的是一種反向索引,所謂反向索引:就是從關鍵字到文檔的映射過程,保存這種映射這種信息的索引稱爲反向索引

inverted_index_thumb.jpg

  • 左邊保存的是字符串序列
  • 右邊是字符串的文檔(Document)編號鏈表,稱爲倒排表(Posting List)

字段串列表和文檔編號鏈表二者構成了一個字典。如今想搜索」lucene」,那麼索引直接告訴咱們,包含有」lucene」的文檔有:2,3,10,35,92,而無需在整個文檔庫中逐個查找。若是是想搜既包含」lucene」又包含」solr」的文檔,那麼與之對應的兩個倒排表去交集便可得到:三、十、3五、92。

索引建立

假設有以下兩個原始文檔:
文檔一:Students should be allowed to go out with their friends, but not allowed to drink beer.
文檔二:My friend Jerry went to school to see his students but found them drunk which is not allowed.
建立過程大概分爲以下步驟:
index-build

一:把原始文檔交給分詞組件(Tokenizer)
分詞組件(Tokenizer)會作如下幾件事情(這個過程稱爲:Tokenize),處理獲得的結果是詞彙單元(Token)

  1. 將文檔分紅一個一個單獨的單詞
  2. 去除標點符號
  3. 去除停詞(stop word)
    • 所謂停詞(Stop word)就是一種語言中沒有具體含義,於是大多數狀況下不會做爲搜索的關鍵詞,這樣一來建立索引時能減小索引的大小。英語中停詞(Stop word)如:」the」、」a」、」this」,中文有:」的,得」等。不一樣語種的分詞組件(Tokenizer),都有本身的停詞(stop word)集合。通過分詞(Tokenizer)後獲得的結果稱爲詞彙單元(Token)。上例子中,便獲得如下詞彙單元(Token)
      "Students","allowed","go","their","friends","allowed","drink","beer","My","friend","Jerry","went","school","see","his","students","found","them","drunk","allowed"

二:詞彙單元(Token)傳給語言處理組件(Linguistic Processor)
語言處理組件(linguistic processor)主要是對獲得的詞元(Token)作一些語言相關的處理。對於英語,語言處理組件(Linguistic Processor)通常作如下幾點:

  1. 變爲小寫(Lowercase)。
  2. 將單詞縮減爲詞根形式,如」cars」到」car」等。這種操做稱爲:stemming。
  3. 將單詞轉變爲詞根形式,如」drove」到」drive」等。這種操做稱爲:lemmatization。

語言處理組件(linguistic processor)處理獲得的結果稱爲詞(Term),例子中通過語言處理後獲得的詞(Term)以下:

"student","allow","go","their","friend","allow","drink","beer","my","friend","jerry","go","school","see","his","student","find","them","drink","allow"。

通過語言處理後,搜索drive時drove也能被搜索出來。Stemming 和 lemmatization的異同:

  • 相同之處:
    1. Stemming和lemmatization都要使詞彙成爲詞根形式。
  • 二者的方式不一樣:
    1. Stemming採用的是」縮減」的方式:」cars」到」car」,」driving」到」drive」。
    2. Lemmatization採用的是」轉變」的方式:」drove」到」drove」,」driving」到」drive」。
  • 二者的算法不一樣:
    1. Stemming主要是採起某種固定的算法來作這種縮減,如去除」s」,去除」ing」加」e」,將」ational」變爲」ate」,將」tional」變爲」tion」。
    2. Lemmatization主要是採用事先約定的格式保存某種字典中。好比字典中有」driving」到」drive」,」drove」到」drive」,」am, is, are」到」be」的映射,作轉變時,按照字典中約定的方式轉換就能夠了。
    3. Stemming和lemmatization不是互斥關係,是有交集的,有的詞利用這兩種方式都能達到相同的轉換。

三:獲得的詞(Term)傳遞給索引組件(Indexer)

  1. 利用獲得的詞(Term)建立一個字典
    Term    Document ID
    student     1
    allow       1
    go          1
    their       1
    friend      1
    allow       1
    drink       1
    beer        1
    my          2
    friend      2
    jerry       2
    go          2
    school      2
    see         2
    his         2
    student     2
    find        2
    them        2
    drink       2
    allow       2
  2. 對字典按字母順序排序:
    Term    Document ID
    allow       1
    allow       1
    allow       2
    beer        1
    drink       1
    drink       2
    find        2
    friend      1
    friend      2
    go          1
    go          2
    his         2
    jerry       2
    my          2
    school      2
    see         2
    student     1
    student     2
    their       1
    them        2
  3. 合併相同的詞(Term)成爲文檔倒排(Posting List)鏈表postlist
    • Document Frequency:文檔頻次,表示多少文檔出現過此詞(Term)
    • Frequency:詞頻,表示某個文檔中該詞(Term)出現過幾回

對詞(Term) 「allow」來說,總共有兩篇文檔包含此詞(Term),詞(Term)後面的文檔鏈表總共有兩個,第一個表示包含」allow」的第一篇文檔,即1號文檔,此文檔中,」allow」出現了2次,第二個表示包含」allow」的第二個文檔,是2號文檔,此文檔中,」allow」出現了1次

至此索引建立完成,搜索」drive」時,」driving」,」drove」,」driven」也可以被搜到。由於在索引中,」driving」,」drove」,」driven」都會通過語言處理而變成」drive」,在搜索時,若是您輸入」driving」,輸入的查詢語句一樣通過分詞組件和語言處理組件處理的步驟,變爲查詢」drive」,從而能夠搜索到想要的文檔。

搜索步驟

搜索」microsoft job」,用戶的目的是但願在微軟找一份工做,若是搜出來的結果是:」Microsoft does a good job at software industry…」,這就與用戶的指望偏離太遠了。如何進行合理有效的搜索,搜索出用戶最想要得結果呢?搜索主要有以下步驟:

一:對查詢內容進行詞法分析、語法分析、語言處理

  1. 詞法分析:區分查詢內容中單詞和關鍵字,好比:english and janpan,」and」就是關鍵字,」english」和」janpan」是普通單詞。
  2. 根據查詢語法的語法規則造成一棵樹
    grammer_tree.jpg
  3. 語言處理,和建立索引時處理方式是同樣的。好比:leaned–>lean,driven–>drive

二:搜索索引,獲得符合語法樹的文檔集合
三:根據查詢語句與文檔的相關性,對結果進行排序

咱們把查詢語句也看做是一個文檔,對文檔與文檔之間的相關性(relevance)進行打分(scoring),分數高比較越相關,排名就越靠前。固然還能夠人工影響打分,好比百度搜索,就不必定徹底按照相關性來排名的。

如何評判文檔之間的相關性?一個文檔由多個(或者一個)詞(Term)組成,好比:」solr」, 「toturial」,不一樣的詞可能重要性不同,好比solr就比toturial重要,若是一個文檔出現了10次toturial,但只出現了一次solr,而另外一文檔solr出現了4次,toturial出現一次,那麼後者頗有可能就是咱們想要的搜的結果。這就引伸出權重(Term weight)的概念。

權重表示該詞在文檔中的重要程度,越重要的詞固然權重越高,所以在計算文檔相關性時影響力就更大。經過詞之間的權重獲得文檔相關性的過程叫作空間向量模型算法(Vector Space Model)

影響一個詞在文檔中的重要性主要有兩個方面:

  • Term Frequencey(tf),Term在此文檔中出現的頻率,ft越大表示越重要
  • Document Frequency(df),表示有多少文檔中出現過這個Trem,df越大表示越不重要
    物以希爲貴,你們都有的東西,天然就不那麼貴重了,只有你專有的東西表示這個東西很珍貴,權重的公式:

空間向量模型

文檔中詞的權重看做一個向量

Document = {term1, term2, …… ,term N}
Document Vector = {weight1, weight2, …… ,weight N}

把欲要查詢的語句看做一個簡單的文檔,也用向量表示:

Query = {term1, term 2, …… , term N}
Query Vector = {weight1, weight2, …… , weight N}

把搜索出的文檔向量及查詢向量放入N維度的空間中,每一個詞表示一維:

夾角越小,表示越類似,相關性越大

Document

Document是Solr索引(動詞,indexing)和搜索的最基本單元,它相似於關係數據庫表中的一條記錄,能夠包含一個或多個字段(Field),每一個字段包含一個name和文本值。字段在被索引的同時能夠存儲在索引中,搜索時就能返回該字段的值,一般文檔都應該包含一個能惟一表示該文檔的id字段。例如:

1
2
3
4
5
6
7
8
<doc>
    <field name="id">company123</field>
    <field name="companycity">Atlanta</field>
    <field name="companystate">Georgia</field>
    <field name="companyname">Code Monkeys R Us, LLC</field>
    <field name="companydescription">we write lots of code</field>
    <field name="lastmodified">2013-06-01T15:26:37Z</field>
</doc>

Schema

Solr中的Schema相似於關係數據庫中的表結構,它以schema.xml的文本形式存在在conf目錄下,在添加文當到索引中時須要指定Schema,Schema文件主要包含三部分:字段(Field)、字段類型(FieldType)、惟一鍵(uniqueKey)

  • 字段類型(FieldType):用來定義添加到索引中的xml文件字段(Field)中的類型,如:int,String,date,
  • 字段(Field):添加到索引文件中時的字段名稱
  • 惟一鍵(uniqueKey):uniqueKey是用來標識文檔惟一性的一個字段(Feild),在更新和刪除時用到

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<schema name="example"version="1.5">
    <field name="id"type="string"indexed="true"stored="true"required="true"multiValued="false"/>
    <field name="title"type="text_general"indexed="true"stored="true"multiValued="true"/>
 
    <uniqueKey>id</uniqueKey>
    <fieldType name="string"class="solr.StrField"sortMissingLast="true"/>
    <fieldType name="text_general"class="solr.TextField"positionIncrementGap="100">
          <analyzer type="index">
            <tokenizerclass="solr.StandardTokenizerFactory"/>
            <filterclass="solr.StopFilterFactory"ignoreCase="true"words="stopwords.txt"/>
            <!-- inthisexample, we will only use synonyms at query time
            <filterclass="solr.SynonymFilterFactory"synonyms="index_synonyms.txt"ignoreCase="true"expand="false"/>
            -->
            <filterclass="solr.LowerCaseFilterFactory"/>
          </analyzer>
          <analyzer type="query">
            <tokenizerclass="solr.StandardTokenizerFactory"/>
            <filterclass="solr.StopFilterFactory"ignoreCase="true"words="stopwords.txt"/>
            <filterclass="solr.SynonymFilterFactory"synonyms="synonyms.txt"ignoreCase="true"expand="true"/>
            <filterclass="solr.LowerCaseFilterFactory"/>
          </analyzer>
    </fieldType>
</schema>

Field

在Solr中,字段(Field)是構成Document的基本單元。對應於數據庫表中的某一列。字段是包括了名稱,類型以及對字段對應的值如何處理的一種元數據。好比:

<field name="name" type="text_general" indexed="true" stored="true"/>
  • Indexed:Indexed=true時,表示字段會加被Sorl處理加入到索引中,只有被索引的字段才能被搜索到。
  • Stored:Stored=true,字段值會以保存一份原始內容在在索引中,能夠被搜索組件組件返回,考慮到性能問題,對於長文本就不適合存儲在索引中。

Field Type

Solr中每一個字段都有一個對應的字段類型,好比:float、long、double、date、text,Solr提供了豐富字段類型,同時,咱們還能夠自定義適合本身的數據類型,例如:

1
2
3
4
5
6
7
8
9
10
<!-- Ik 分詞器 -->
 <fieldType name="text_cn_stopword"class="solr.TextField">
     <analyzer type="index">
         <tokenizerclass="org.wltea.analyzer.lucene.IKAnalyzerSolrFactory"useSmart="false"/>
     </analyzer>
     <analyzer type="query">
         <tokenizerclass="org.wltea.analyzer.lucene.IKAnalyzerSolrFactory"useSmart="true"/>
     </analyzer>
 </fieldType>
 <!-- Ik 分詞器 -->

Solrconfig:

若是把Schema定義爲Solr的Model的話,那麼Solrconfig就是Solr的Configuration,它定義Solr若是處理索引、高亮、搜索等不少請求,同時還指定了緩存策略,用的比較多的元素包括:

  • 指定索引數據路徑
1
2
3
4
5
6
<!--
Used to specify an alternate directory to hold all index data
other than thedefault./data under the Solr home.
If replication is in use,thisshould match the replication configuration.
-->
<dataDir>${solr.data.dir:./solr/data}</dataDir>
  • 緩存參數
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<filterCache
  class="solr.FastLRUCache"
  size="512"
  initialSize="512"
  autowarmCount="0"/>
 
<!-- queryResultCache caches results of searches - ordered lists of
     document ids (DocList) based on a query, a sort, and the range
     of documents requested.  -->
 <queryResultCache
  class="solr.LRUCache"
  size="512"
  initialSize="512"
  autowarmCount="0"/>
 
 <!-- documentCache caches Lucene Document objects (the stored fieldsforeach document).
   Since Lucene internal document ids aretransient,thiscache will not be autowarmed.  -->
 <documentCache
  class="solr.LRUCache"
  size="512"
  initialSize="512"
  autowarmCount="0"/>
  • 請求處理器
    請求處理器用於接收HTTP請求,處理搜索後,返回響應結果的處理器。好比:query請求:
1
2
3
4
5
6
7
8
9
<!-- A request handler that returns indented JSON bydefault-->
<requestHandler name="/query"class="solr.SearchHandler">
     <lst name="defaults">
       <str name="echoParams">explicit</str>
       <str name="wt">json</str>
       <str name="indent">true</str>
       <str name="df">text</str>
     </lst>
</requestHandler>
每一個請求處理器包括一系列可配置的搜索參數,例如:wt,indent,df等等。
  • 搜索組件

MySQL

  1. 拷貝mysql-connector-java-5.1.25-bin.jar到E:\solr-4.8.0\example\solr-webapp\webapp\WEB-INF\lib目錄下面
  2. 配置E:\solr-4.8.0\example\solr\collection1\conf\solrconfig.xml
1
2
3
4
5
6
<requestHandlername="/dataimport"
     class="org.apache.solr.handler.dataimport.DataImportHandler">
       <lstname="defaults">
          <strname="config">data-config.xml</str>
       </lst>
</requestHandler>
  1. 導入依賴庫文件:
1
<lib dir="../../../dist/" regex="solr-dataimporthandler-\d.*\.jar"/>
加在
1
<lib dir="../../../dist/" regex="solr-cell-\d.*\.jar" />
前面。
  1. 建立E:\solr-4.8.0\example\solr\collection1\conf\data-config.xml,指定MySQL數據庫地址,用戶名、密碼以及創建索引的數據表
    <?xmlversion="1.0"encoding="UTF-8"?>
          <dataConfig> 
                  <dataSourcetype="JdbcDataSource"
                              driver="com.mysql.jdbc.Driver"
                              url="jdbc:mysql://localhost:3306/django_blog"
                              user="root"
                              password=""/> 
                      <documentname="blog"> 
                              <entityname="blog_blog"pk="id"
                                      query="select id,title,content from blog_blog"
                                      deltaImportQuery="select id,title,content from blog_blog where ID='${dataimporter.delta.id}'" 
                                      deltaQuery="select id  from blog_blog where add_time > '${dataimporter.last_index_time}'" 
                                      deletedPkQuery="select id  from blog_blog where id=0"> 
                                   <fieldcolumn="id"name="id"/> 
                                   <fieldcolumn="title"name="title"/> 
                                   <fieldcolumn="content"name="content"/> 
                              </entity> 
                     </document>
          </dataConfig>
    • query 用於初次導入到索引的sql語句。
      • 考慮到數據表中的數據量很是大,好比千萬級,不可能一次索引完,所以須要分批次完成,那麼查詢語句query要設置兩個參數:${dataimporter.request.length} ${dataimporter.request.offset}
      • query=」select id,title,content from blog_blog limit ${dataimporter.request.length} offset ${dataimporter.request.offset}」
      • 請求:http://localhost:8983/solr/collection2/dataimport?command=full-import&commit=true&clean=false&offset=0&length=10000
    • deltaImportQuery 根據ID取得須要進入的索引的單條數據。
    • deltaQuery 用於增量索引的sql語句,用於取得須要增量索引的ID。
    • deletedPkQuery 用於取出須要從索引中刪除文檔的的ID
  2. 爲數據庫表字段創建域(field),編輯E:\solr-4.8.0\example\solr\collection1\conf\schema.xml:
<!-- mysql -->
   <fieldname="id"type="string"indexed="true"stored="true"required="true"/>
   <fieldname="title"type="text_cn"indexed="true"stored="true"termVectors="true"termPositions="true"termOffsets="true"/>
   <fieldname="content"type="text_cn"indexed="true"stored="true"termVectors="true"termPositions="true"termOffsets="true"/>
<!-- mysql -->
  1. 配置增量索引更新文件

參考:

Mongodb

  1. 安裝mongo-connector,最好使用手動安裝方式:
    <code>git clone https://github.com/10gen-labs/mongo-connector.git cd mongo-connector #安裝前修改mongo_connector/constants.py的變量:設置DEFAULT_COMMIT_INTERVAL = 0 python setup.py install </code>

    默認是不會自動提交了,這裏設置成自動提交,不然mongodb數據庫更新,索引這邊無法同時更新,或者在命令行中能夠指定是否自動提交,不過我如今還沒發現。

  2. 配置schema.xml,把mongodb中須要加上索引的字段配置到schema.xml文件中:
    <?xmlversion="1.0"encoding="UTF-8"?>
     <schemaname="example"version="1.5">
         <fieldname="_version_"type="long"indexed="true"stored="true"/>
         <fieldname="_id"type="string"indexed="true"stored="true"required="true"multiValued="false"/>
         <fieldname="body"type="string"indexed="true"stored="true"/>
         <fieldname="title"type="string"indexed="true"stored="true"multiValued="true"/>
         <fieldname="text"type="text_general"indexed="true"stored="false"multiValued="true"/>  
         <uniqueKey>_id</uniqueKey>
         <defaultSearchField>title</defaultSearchField>
         <solrQueryParserdefaultOperator="OR"/>
         <fieldTypename="string"class="solr.StrField"sortMissingLast="true"/>
         <fieldTypename="long"class="solr.TrieLongField"precisionStep="0"positionIncrementGap="0"/>
         <fieldTypename="text_general"class="solr.TextField"positionIncrementGap="100">
           <analyzertype="index">
             <tokenizerclass="solr.StandardTokenizerFactory"/>
             <filterclass="solr.StopFilterFactory"ignoreCase="true"words="stopwords.txt"/>
             <filterclass="solr.LowerCaseFilterFactory"/>
           </analyzer>
           <analyzertype="query">
             <tokenizerclass="solr.StandardTokenizerFactory"/>
             <filterclass="solr.StopFilterFactory"ignoreCase="true"words="stopwords.txt"/>
             <filterclass="solr.SynonymFilterFactory"synonyms="synonyms.txt"ignoreCase="true"expand="true"/>
             <filterclass="solr.LowerCaseFilterFactory"/>
           </analyzer>
         </fieldType>
     </schema>
  3. 啓動Mongod:
    <code>mongod --replSet myDevReplSet --smallfiles </code>

    初始化:rs.initiate()

  4. 啓動mongo-connector:
    <code>E:\Users\liuzhijun\workspace\mongo-connector\mongo_connector\doc_managers&gt;mongo-connector -m localhost:27017 -t http://localhost:8983/solr/collection2 -n s_soccer.person -u id -d ./solr_doc_manager.py </code>
    • -m:mongod服務
    • -t:solr服務
    • -n:mongodb命名空間,監聽database.collection,多個命名空間逗號分隔
    • -u:uniquekey
    • -d:處理文檔的manager文件

    注意:mongodb一般使用_id做爲uniquekey,而Solrmore使用id做爲uniquekey,若是不作處理,索引文件時將會失敗,有兩種方式來處理這個問題:

    1. 指定參數--unique-key=id到mongo-connector,Mongo Connector 就能夠翻譯把_id轉換到id。
    2. 把schema.xml文件中的:
      <code>&lt;uniqueKey&gt;id&lt;uniqueKey&gt; </code>

      替換成

      <code>&lt;uniqueKey&gt;_id&lt;/uniqueKey&gt; </code>

      同時還要定義一個_id的字段:

      <code>&lt;field name="_id" type="string" indexed="true" stored="true" /&gt; </code>
    3. 啓動時若是報錯:
      <code>2014-06-18 12:30:36,648 - ERROR - OplogThread: Last entry no longer in oplog cannot recover! Collection(Database(MongoClient('localhost', 27017), u'local'), u'oplog.rs') </code>

      清空E:\Users\liuzhijun\workspace\mongo-connector\mongo_connector\doc_managers\config.txt中的內容,須要刪除索引目錄下的文件從新啓動

  5. 測試 mongodb中的數據變化都會同步到solr中去。
相關文章
相關標籤/搜索