使用Apache Solr對數據庫建立索引(包括處理CLOB、CLOB)

原文地址:http://www.blogjava.net/conans/articles/379546.html

以下資料整理自網絡,覺的有必要合併在一起,這樣方便查看。主要分爲兩部分,第一部分是對《db-data-config.xml》的配置內容的講解(屬於高級內容),第二部分是DataImportHandler(屬於基礎),第三部分是對db-data-config.xml的進階(這個國內可能還沒有人寫過啊,我在google、baidu上都沒有搜索到,最後可是拔代碼,看solr的英文文檔找的)

第一部分是對《db-data-config.xml》

query是獲取全部數據的SQL
deltaImportQuery是獲取增量數據時使用的SQL
deltaQuery是獲取pk的SQL
parentDeltaQuery是獲取父Entity的pk的SQL

 

Full Import工作原理
執行本Entity的Query,獲取所有數據;
針對每個行數據Row,獲取pk,組裝子Entity的Query;
執行子Entity的Query,獲取子Entity的數據。

 

Delta Import工作原理
查找子Entity,直到沒有爲止;
執行Entity的deltaQuery,獲取變化數據的pk;
合併子Entity parentDeltaQuery得到的pk;
針對每一個pk Row,組裝父Entity的parentDeltaQuery;
執行parentDeltaQuery,獲取父Entity的pk;
執行deltaImportQuery,獲取自身的數據;
如果沒有deltaImportQuery,就組裝Query

 

限制
子Entity的query必須引用父Entity的pk
子Entity的parentDeltaQuery必須引用自己的pk
子Entity的parentDeltaQuery必須返回父Entity的pk
deltaImportQuery引用的必須是自己的pk

第二部分是DataImportHandler

關於DataImportHandler的具體使用方法,詳見下文,如果你英文超級好,那看這個鏈接吧:http://wiki.apache.org/solr/DataImportHandler

 

  大多數的應用程序將數據存儲在關係數據庫、xml文件中。對這樣的數據進行搜索是很常見的應用。所謂的DataImportHandler提供一種可配置的方式向solr導入數據,可以一次全部導入,也可以增量導入。

      概覽

         目

  •      能夠讀取關係數據庫中的數據。
  •      通過可配置的方式,能夠將數據庫中多列、多表的數據生成solr文檔  
  •      能夠通過solr文檔更新solr
  •      提供 通過配置文件就能夠導入所有數據的能力
  •       能夠發現並處理 由insert、update帶來的變化(我們假定在表中有一個叫做“last-modified的列”)
  •       能夠配置 “完全導入”和“增量導入”的時間
  •       讓讀取xml文件,並建立索引成爲可配置。
  •       能夠將 其他的數據源(例如:ftp,scp,etc)或者其他格式的文檔(Json,csv)以插件的形式集成到項目中。

          設計思路

           這個Handler首先要在solrconfig.xml文件中配置下,如下所示。

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

      從它的名字上,我們或許也可以猜到,
DataImportHandler正是requestHandler的實現。我們一共需要在兩個地方配置文件中進行一些配置。
  • solrconfig.xml 。 data-config.xml必須在這個文件中配置,datasource也可以。不過,一般將datasource放在data-config.xml文件中。
  • data-config.xml
  1.  
    1.    怎樣獲取數據?(查詢語句、url等等)
    2.   要讀什麼樣的數據(關係數據庫中的列、或者xml的域)
    3.    做什麼樣的處理(修改/添加/刪除)

      跟關係數據庫一起使用

             下面幾個步驟是必要的.

  •      定義一個data-config.xml 文件,並這個它的路徑配置到solrconfig.xml 中關於DataImportHandler的配置中。
  •       給出Connection的信息(假設你選擇在solrconfig中配置datasource)
  • 打開DataImportHandler頁面去驗證,是否該配置的都配置好了。http://localhost:8983/solr/dataimport
  • 使用“完全導入”命令將數據從數據庫中導出,並提交給solr建立索引
  • 使用“增量導入”命令對數據庫發生的變化的數據導出,並提交給solr建立索引。

           配置數據源

        將dataSource標籤直接添加到dataConfig下面,即成爲dataConfig的子元素.

       
<dataSource type="JdbcDataSource" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost/dbname" user="db_username" password="db_password"/>

  •       數據源也可以配置在solrconfig.xml中
  • 屬性type 指定了實現的類型。它是可選的。默認的實現是JdbcDataSource。
  • 屬性 name  是datasources的名字,當有多個datasources時,可以使用name屬性加以區分
  • 其他的屬性都是隨意的,根據你使用的DataSource實現而定。
  • 當然 你也可以實現自己的DataSource。

          多數據

     一個配置文件可以配置多個數據源。增加一個dataSource元素就可以增加一個數據源了。name屬性可以區分不同的數據源。如果配置了多於一個的數據源,那麼要注意將name配置成唯一的。

   例如:

<dataSource type="JdbcDataSource" name="ds-1" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://db1-host/dbname" user="db_username" password="db_password"/>

<dataSource type="JdbcDataSource" name="ds-2" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://db2-host/dbname" user="db_username" password="db_password"/>

 然後這樣使用
    
..

<entity name="one" dataSource="ds-1" ...>

   ..

</entity>

<entity name="two" dataSource="ds-2" ...>

   ..

</entity>

..

    
配置JdbcDataSource

   

JdbcDataSource中的屬性有
  • driver(必需的):jdbc驅動名稱
  • url(必需的):jdbc鏈接
  • user:用戶名
  • password:密碼
  • 批量大小:jdbc鏈接中的批量大小

任何其他的在JdbcDataSource中配置的屬性,都會被直接傳給jdbc driver

配置data-config.xml

   solr document是schema,它的域上的值可能來自於多個表.

   data-config.xml的根元素是document。一個document元素代表了一種文檔。一個 document元素中包含了一個或者多個root實體。一個root實體包含着一些子實體,這些子實體能夠包含其他的實體。實體就是,關係數據庫上的表或者視圖。每個實體都能夠包含多個域,每個域對應着數據庫返回結果中的一列。域的名字跟列的名字默認是一樣的。如果一個列的名字跟solr field的名字不一樣,那麼屬性name就應該要給出。其他的需要的屬性在solrschema.xml文件中配置。

    爲了能夠從數據庫中取得想要的數據,我們的設計支持標準sql規範。這使得用戶能夠使用他任何想要的sql語句。root實體是一箇中心表,使用它的列可以把表連接在一起。

     dataconfig的結構

    dataconfig的結構不是一成不變的,entity和field元素中的屬性是隨意的,這主要取決於processor和transformer。

      以下是entity的默認屬性

  •  name(必需的):name是唯一的,用以標識entity
  • processor:只有當datasource不是RDBMS時纔是必需的。默認值是SqlEntityProcessor
  • transformer:轉換器將會被應用到這個entity上,詳情請瀏覽transformer部分。
  • pk:entity的主鍵,它是可選的,但使用“增量導入”的時候是必需。它跟schema.xml中定義的uniqueKey沒有必然的聯繫,但它們可以相同。
  • rootEntity:默認情況下,document元素下就是根實體了,如果沒有根實體的話,直接在實體下面的實體將會被看做跟實體。對於根實體對應的數據庫中返回的數據的每一行,solr都將生成一個document。

     一下是SqlEntityProcessor的屬性

  • query (required) :sql語句

  • deltaQuery : 只在“增量導入”中使用

  • parentDeltaQuery : 只在“增量導入”中使用

  • deletedPkQuery : 只在“增量導入”中使用

  • deltaImportQuery : (只在“增量導入”中使用) . 如果這個存在,那麼它將會在“增量導入”中導入phase時代替query產生作用。這裏有一個命名空間的用法${dataimporter.delta.}詳情請看solr1.4.

Commands

The handler 通過httprequest 向外界提供它的API . 以下是一些或許你會用到的操作

  • full-import : "完全導入"這個操作可以通過訪問URL http://:/solr/dataimport?command=full-import 完成。

    • 這個操作,將會新起一個線程。response中的attribute屬性將會顯示busy。

    • 這個操作執行的時間取決於數據集的大小。

    • 當這個操作運行完了以後,它將在conf/dataimport.properties這個文件中記錄下這個操作的開始時間

    • 當“增量導入”被執行時,stored timestamp這個時間戳將會被用到

    • solr的查詢在“完全導入”時,不是阻塞的

    • 它還有下面一些參數:

      • clean : (default 'true'). 決定在建立索引之前,刪除以前的索引。

      • commit: (default 'true'). 決定這個操作之後是否要commit

      • optimize: (default 'true'). 決定這個操作之後是否要優化。

      • debug : (default false). 工作在debug模式下。詳情請看 the interactive development mode (see here)

  • delta-import : 當遇到一些增量的輸入,或者發生一些變化時使用`DataImport - 航夢 - 火星?地球? http://:/solr/dataimport?command=delta-import . 它同樣支持  clean, commit, optimize and debug 這幾個參數.

  • status : 想要知道命令執行的狀態 , 訪問 URL http://:/solr/dataimport .它給出了關於文檔創建、刪除,查詢、結果獲取等等的詳細狀況。

  • reload-config : 如果data-config.xml已經改變,你不希望重啓solr,而要重新加載配置時,運行一下的命令http://:/solr/dataimport?command=reload-config

  • abort : 你可以通過訪問 url http://:/solr/dataimport?command=abort 來終止一個在運行的操作

 

Full Import 例子

讓我們來看下面的例子. 假設我們數據庫中的表結構如下:

DataImport - 航夢 - 火星?地球?

This is a relational model of the same schema that Solr currently ships with. 我們使用這個例子來爲我們的DataImportHandler建data-config.xml。 我們已經使用這個結構在HSQLDB上建立了一個數據庫. 好,現在開始了, 跟着下面的步驟走: 

  1. 下載 example-solr-home.jar 並使用 jar解壓  jar -xvf example-solr-home.jar ,解壓到你的本地系統. 這個jar文件包含了一個完整的solrhome(裏面的配置文件很齊全了)和一個RSS的例子。它也包含了一個hssqldb數據庫的例子.

  2. 在 example-solr-home目錄, 這裏有一個 solr.war. 拷貝 這個 war 文件到你的 tomcat/jetty webapps 文件夾.  這個 war file 也包含了hsqldb的JDBC driver. 如果你想在你已經有了的solr項目中部署,你只需要將  'dataimport.jar' 拷貝到 你的solr項目的 WEB-INF/lib 目錄下。

  3. 使用example-data-config目錄下的solr目錄作爲你solrhome

  4. 訪問 DataImport - 航夢 - 火星?地球? http://localhost:8983/solr/dataimport 驗證一下配置

  5. 訪問 DataImport - 航夢 - 火星?地球? http://localhost:8983/solr/dataimport?command=full-import 執行一個“完全導入”

上面給出的solr目錄是一個多核的solr home。它有兩個核,一個是DB example,一個是RSSexample(新屬性)。

這個例子的data-config.xml 如下:

<dataConfig>

<dataSource driver="org.hsqldb.jdbcDriver" url="jdbc:hsqldb:/temp/example/ex" user="sa" />

    <document name="products">

        <entity name="item" query="select * from item">

            <field column="ID" name="id" />

            <field column="NAME" name="name" />

            <field column="MANU" name="manu" />

            <field column="WEIGHT" name="weight" />

            <field column="PRICE" name="price" />

            <field column="POPULARITY" name="popularity" />

            <field column="INSTOCK" name="inStock" />

            <field column="INCLUDES" name="includes" />



            <entity name="feature" query="select description from feature where item_id='${item.ID}'">

                <field name="features" column="description" />

            </entity>

            <entity name="item_category" query="select CATEGORY_ID from item_category where item_id='${item.ID}'">

                <entity name="category" query="select description from category where id = '${item_category.CATEGORY_ID}'">

                    <field column="description" name="cat" />

                </entity>

            </entity>

        </entity>

    </document>

</dataConfig>

這裏, 根實體是一個名叫“item”的表,它的主鍵是id。我們使用語句 "select * from item"讀取數據. 每一項都擁有多個特性。看下面feature實體的查詢語句

   <entity name="feature" query="select description from feature where item_id='${item.id}'">

       <field name="feature" column="description" />

   </entity> 

     

feature表中的外鍵item_id跟item中的主鍵連在一起從數據庫中取得該row的數據。相同地,我們將item和category連表(它們是多對多的關係)。注意,我們是怎樣使用中間表和標準sql連表的

 <entity name="item_category" query="select category_id from item_category where item_id='${item.id}'">
                <entity name="category" query="select description from category where id = '${item_category.category_id}'">
                    <field column="description" name="cat" />
                </entity>
            </entity>

短一點的 data-config

在上面的例子中,這裏有好幾個從域到solr域之間的映射。如果域的名字和solr中域的名字是一樣的話,完全避免使用在實體中配置域也是可以的。當然,如果你需要使用轉換器的話,你還是需要加上域實體的。

下面是一個更短的版本

<dataConfig>

    <dataSource driver="org.hsqldb.jdbcDriver" url="jdbc:hsqldb:/temp/example/ex" user="sa" />

    <document>

        <entity name="item" query="select * from item">                    

            <entity name="feature" query="select description as features from feature where item_id='${item.ID}'"/>            

            <entity name="item_category" query="select CATEGORY_ID from item_category where item_id='${item.ID}'">

                <entity name="category" query="select description as cat from category where id = '${item_category.CATEGORY_ID}'"/>                        

            </entity>

        </entity>

    </document>

</dataConfig>


使用“增量導入”命令

你可以通過訪問URL DataImport - 航夢 - 火星?地球? http://localhost:8983/solr/dataimport?command=delta-import 來使用增量導入。操作將會新起一個線程,response中的屬性statue也將顯示busy now。操作執行的時間取決於你的數據集的大小。在任何時候,你都可以通過訪問   http://localhost:8983/solr/dataimport 來查看狀態。

當 增量導入被執行的時候,它讀取存儲在conf/dataimport.properties中的“start time”。它使用這個時間戳來執行增量查詢,完成之後,會更新這個放在conf/dataimport.properties中的時間戳。

Delta-Import 例子

我們將使用跟“完全導入”中相同的數據庫。注意,數據庫已經被更新了,每個表都包含有一個額外timestamp類型的列  叫做last_modified。或許你需要重新下載數據庫,因爲它最近被更新了。我們使用這個時間戳的域來區別出那一行是上次索引以來有更新的。

看看下面的這個 data-config.xml

<dataConfig>

    <dataSource driver="org.hsqldb.jdbcDriver" url="jdbc:hsqldb:/temp/example/ex" user="sa" />

    <document name="products">

            <entity name="item" pk="ID" query="select * from item"

                deltaQuery="select id from item where last_modified > '${dataimporter.last_index_time}'">           



            <entity name="feature" pk="ITEM_ID" 

                    query="select description as features from feature where item_id='${item.ID}'">                

            </entity>

            <entity name="item_category" pk="ITEM_ID, CATEGORY_ID"

                    query="select CATEGORY_ID from item_category where ITEM_ID='${item.ID}'">

                <entity name="category" pk="ID"

                       query="select description as cat from category where id = '${item_category.CATEGORY_ID}'">                    

                </entity>

            </entity>

        </entity>

    </document>

</dataConfig>

注意到item實體的 屬性deltaquery了嗎,它包含了一個能夠查出最近更新的sql語句。注意,變量{dataimporter.last_index_time} 是DataImporthandler傳過來的變量,我們叫它時間戳,它指出“完全導入”或者“部分導入”的最後運行時間。你可以在data-config.xml文件中的sql的任何地方使用這個變量,它將在processing這個過程中被賦值。

DataImport - 航夢 - 火星?地球? 注意

  • 上面例子中deltaQuery 只能夠發現item中的更新,而不能發現其他表的。你可以像下面那樣在一個sql語句中指定所有的表的更新。這裏要特別說明一下的就是,它的細節對於一個使用者來說是一個不錯的練習。DataImport - 航夢 - 火星?地球?

        deltaQuery="select id from item where id in

                                (select item_id as id from feature where last_modified > '${dataimporter.last_index_time}')

                                or id in 

                                (select item_id as id from item_category where item_id in 

                                    (select id as item_id from category where last_modified > '${dataimporter.last_index_time}')

                                or last_modified > '${dataimporter.last_index_time}')

                                or last_modified > '${dataimporter.last_index_time}'"

  • 寫一個類似上面的龐大的deltaQuery 並不是一件很享受的工作,我們還是選擇其他的方法來達到這個目的

 

<dataConfig>

    <dataSource driver="org.hsqldb.jdbcDriver" url="jdbc:hsqldb:/temp/example/ex" user="sa" />

    <document>

            <entity name="item" pk="ID" query="select * from item"

                deltaQuery="select id from item where last_modified > '${dataimporter.last_index_time}'">

                <entity name="feature" pk="ITEM_ID" 

                    query="select DESCRIPTION as features from FEATURE where ITEM_ID='${item.ID}'"

                    deltaQuery="select ITEM_ID from FEATURE where last_modified > '${dataimporter.last_index_time}'"

                    parentDeltaQuery="select ID from item where ID=${feature.ITEM_ID}"/>

                

            

            <entity name="item_category" pk="ITEM_ID, CATEGORY_ID"

                    query="select CATEGORY_ID from item_category where ITEM_ID='${item.ID}'"

                    deltaQuery="select ITEM_ID, CATEGORY_ID from item_category where last_modified > '${dataimporter.last_index_time}'"

                    parentDeltaQuery="select ID from item where ID=${item_category.ITEM_ID}">

                <entity name="category" pk="ID"

                        query="select DESCRIPTION as cat from category where ID = '${item_category.CATEGORY_ID}'"

                        deltaQuery="select ID from category where last_modified > '${dataimporter.last_index_time}'"

                        parentDeltaQuery="select ITEM_ID, CATEGORY_ID from item_category where CATEGORY_ID=${category.ID}"/>

            </entity>

        </entity>

    </document>

</dataConfig>

   

除了根實體(有兩個)以外,這裏一共有三個查詢,每個實體個一個。

查詢語句,爲我們取得需要建立索引的數據。

  • deltaQuery 取得從上次索引更新時間以來有更新的實體的主鍵。

  • parentDeltaQuery 從deltaQuery中取得當前表中更新的行,並把這些行提交給父表。因爲,當子表中的一行發生改變時,我們需要更新它的父表的solr文檔。

下面是一些值得注意的地方:

  • 對於query語句返回的每一行,子實體的query都將被執行一次

  • 對於deltaQuery返回的每一行,parentDeltaQuery都將被執行。

  • 一旦根實體或者子實體中的行發生改變,我們將重新生成包含該行的solr文檔。

 XML/HTTP Datasource使用指南

DataImportHandler 能夠幫我們爲基於HTTP的數據源建立索引. 目前支持REST/XML APIs 和RSS/ATOM Feeds.

配置HttpDataSource

HttpDataSource在dataconfig.xml中的配置看起來應該像這樣: 

  <dataSource type="HttpDataSource" baseUrl="http://host:port/" encoding="UTF-8" connectionTimeout="5000" readTimeout="10000"/>  


屬性:

  • baseUrl (可選): 在Dev/QA/Prod 環境中,host/port改變時,你會用到它。使用這個屬性,你可以找出配置到solrconfig.xml的變化。

  • encoding(可選): 默認情況下,encoding是response 頭使用的encoding.你可以使用這個屬性去覆蓋默認值。

  • connectionTimeout (可選):默認值是5000ms

  • readTimeout (可選): 默認值是10000ms

在 data-config.xml中的配置

 一個 xml/http data source中的實體有下面一些屬性,也可以有上面提到的默認屬性。

  • processor (必需的) : 它的值應該是"XPathEntityProcessor"

  • url (必需的) :  REST API要使用這個api. (能夠被模板化). 假設數據源是一個文件,那麼url應該是這個文件的位置。

  • stream (可選) : 如果xml很大,那麼它應該設爲true

  • forEach(必需的) : xpath表達式,通過這個表達式可以取得想要的值。 如果這裏有多個想要的值,那麼將xpath表達式用“|”分開。如果useSolrAddSchema設爲true的話,這個是可以被忽略的。

  • xsl(可選):使用xsl對xml進行預處理。你需要提供一個文件系統的全路徑,或者一個url。

  • useSolrAddSchema(可選): Set it's value to 'true' if the xml that is fed into this processor has the same schema as that of the solr add xml. No need to mention any fields if it is set to true.

域能夠有以下這些屬性 (此外還有那些默認值):

  • xpath (必需的) : 記錄中的一列,也就是域的xpath表達式 . 如果 該域並不來自任何的一個單一的xml屬性,xpath是可以被忽略的. 我們可以通過轉化器來使用多個xml屬性來合成該域。如果一個域被聲明成多值的,如果xpath表達式生成的也是多值的,那麼 XPathEntityProcessor將會自動處理它,而不需要我們做額外的工作。

  • commonField : 能夠被設爲 (true或者false),假設這個是true值,一旦一個記錄中有這樣的域,那麼其他記錄被寫索引的時候,這個域也會跟着記錄被寫到索引裏面。

如果 一個API支持分塊數據(當一個數據集太大時),可能需要多次調用才能完成這個處理過程。XPathEntityprocessor 通過轉換器支持這個特性。如果轉換器返回的的行帶有屬性“hasMore”,並且這個屬性的值等於true,那麼Processor 將會使用同樣的url模板發出令一次請求(實際的url是需要重新計算的)。一個轉換器也可以傳遞一個完整的url路徑,這個url被包含在屬性 “nextUrl”中,nextUrl的值必需是一個完整的url。

XPathEntityProcessor 通過實現streaming parser來支持取得xpath子集的操作。完整的xpath是不被支持的,但是常見的應用都是受支持的。

HttpDataSource 例子

下載 在DB 部分中的“完全導入”例子,試着去體驗一下。我們將在這裏例子中爲slashotRSS建立索引。

這個例子的data-config配置看起來像這樣。

<dataConfig>

        <dataSource type="HttpDataSource" />

        <document>

                <entity name="slashdot"

                                pk="link"

                                url="http://rss.slashdot.org/Slashdot/slashdot"

                                processor="XPathEntityProcessor"

                                forEach="/RDF/channel | /RDF/item"

                                transformer="DateFormatTransformer">

                                

                        <field column="source" xpath="/RDF/channel/title" commonField="true" />

                        <field column="source-link" xpath="/RDF/channel/link" commonField="true" />

                        <field column="subject" xpath="/RDF/channel/subject" commonField="true" />

                        

                        <field column="title" xpath="/RDF/item/title" />

                        <field column="link" xpath="/RDF/item/link" />

                        <field column="description" xpath="/RDF/item/description" />

                        <field column="creator" xpath="/RDF/item/creator" />

                        <field column="item-subject" xpath="/RDF/item/subject" />

                        <field column="date" xpath="/RDF/item/date" dateTimeFormat="yyyy-MM-dd'T'hh:mm:ss" />

                        <field column="slash-department" xpath="/RDF/item/department" />

                        <field column="slash-section" xpath="/RDF/item/section" />

                        <field column="slash-comments" xpath="/RDF/item/comments" />

                </entity>

        </document>

</dataConfig>


這個data-config有很多值得借鑑的地方。 我建議你看下SlashdotRSS的結構圖,它有一些頭部元素,例如title、link、subject。這些元素將分別通過xpath語法映射到source、source-link、subject這些solr域。這個種子有多個item元素,這些元素包含了真正的新聞信息。所以,我們希望做得是,爲每一個item元素建立一個文檔。

XPathEntityprocessor 是一行一行的讀取xml文件的(這裏的行指的是一個xml元素)。它使用屬性“forEach”去識別每一行 。在這個例子一種“forEach”的值是'/RDF/channel | /RDF/item'。也就是說這個xml有兩種類型的行(這裏使用一個OR的xpath語法,用以支持多個類型) 。當遇到一個行的時候,它會在行的域聲明中讀取儘量多的域。在這個例子中,當它讀到行“/RDF/channel”時,它將會得到3個域。它處理完這個行的時候,它就會意識到,這個行並沒有pk這個域的值,於是它並不會試圖去建立一個solr文檔(即使它去做,它也會失敗)。但是這個三個域都有一個屬性 commonField ,並且它的值是true,所以它將會保留這個域的值,以便後面的行可以使用

它繼續前進,然後遇到/RDF/item ,接着一個個處理這些行。它將會取得除了那個三個域之外的所有域。但是因爲他們是common field。處理器會把公共域也加到這個記錄中,然後寫入索引。

transformer=DateFormatTransformer 又是什麼呢?你可以看一下DateFormatTransformer有關部分。

你可以使用這些特性來從REST API ,例如 rss、atom、xml、其他solr服務器、甚至是格式良好的xhtml文檔,建立索引。我們的xpath語法有它自己的限制(不支持通配符,只可以是全路徑),但是一般的應用是絕對沒有問題的,而且它是基於streaming parser的,它非常快,並且在讀取非常大的xml文件的時候,它的內存消耗始終保持如一。它不支持命名空間,它卻可以處理帶有命名空間的xml文件。當你處理帶有命名空間的xpath的時候,你需要做的是,丟棄命名空間部分,只留下其他的部分(例如,這個標籤,相對應的xpath部分是 subject)。很容易,是吧?而且你不需要寫一行代碼,好好享受吧。DataImport - 航夢 - 火星?地球?

DataImport - 航夢 - 火星?地球? 注意 : 不像數據庫,如果你使用XPathEntityProcessor,想忽略域聲明是不可能。域通過你聲明的xpaths來從xml中解析相應的數據。

例子: 索引 wikipedia

利用下面的data-config.xml文件可以對wikipedia的數據建立索引。從wikipedia下載下來的pages-articles.xml.bz2文件解壓之後大概有18g。

<dataConfig>

        <dataSource type="FileDataSource" encoding="UTF-8" />

        <document>

        <entity name="page" processor="XPathEntityProcessor" stream="true" forEach="/mediawiki/page/" url="/data/enwiki-20080724-pages-articles.xml">

                <field column="id" xpath="/mediawiki/page/id" />

                <field column="title" xpath="/mediawiki/page/title" />

                <field column="revision" xpath="/mediawiki/page/revision/id" />

                <field column="user" xpath="/mediawiki/page/revision/contributor/username" />

                <field column="userId" xpath="/mediawiki/page/revision/contributor/id" />

                <field column="text" xpath="/mediawiki/page/revision/text" />

                <field column="timestamp" xpath="/mediawiki/page/revision/timestamp" />

        </entity>

        </document>

</dataConfig> 


schema.xml中有關的部分如下所示:
<field name="id" type="integer" indexed="true" stored="true" required="true"/>

<field name="title" type="string" indexed="true" stored="false"/>

<field name="revision" type="sint" indexed="true" stored="true"/>

<field name="user" type="string" indexed="true" stored="true"/>

<field name="userId" type="integer" indexed="true" stored="true"/>

<field name="text" type="text" indexed="true" stored="false"/>

<field name="timestamp" type="date" indexed="true" stored="true"/>

<field name="titleText" type="text" indexed="true" stored="true"/>

...

<uniqueKey>id</uniqueKey>

<copyField source="title" dest="titleText"/>



爲7278241個文章建立索引大概花了2個小時40分,內存使用量的峯值在4G左右。

使用“增量導入”命令

只有SqlEntitiProcessor支持增量數據!XPathEntityProcessor還沒有實現它。所以,不幸運的是,現在還不能爲 “增量導入”提供支持。如果你想要在XPathEntityProcessor中實現這些方法,你可以在EntityProcessor.java中看看這些方法的解釋。

Extending the tool with APIs

我們所展現的例子確實沒有多大價值,單靠配置xml文件就滿足所有的需求是不可能的。所以我們提供了一些抽象類,可以通過這些方法來提高功能。

Transformer

每一條從數據庫中取得的數據能夠被直接處理掉,或者通過它創建一個全新的域,它設置能夠返回多行數據。配置文件必須像下面那樣設置。

<entity name="foo" transformer="com.foo.Foo" ... />

DataImport - 航夢 - 火星?地球? 注意-- trasformer的值必須是一個可以使用的classname。如果class包是'org.apache.solr.handler.dataimport' ,包名可以被忽略。solr.也是可以使用的,如果這個class在solr的一個包下的話。這個規則適應所有的可插入的類,像DataSource、EntityProcessor、Evaluator。 

類Foo必須繼承抽象類org.apache.solr.hander.dataimport.Transformer.這個類只有一個抽象方法。

transformer這個屬性可以有多個transformers()(比如 transformer="foo.X,foo.Y") 之間用逗號隔開。 transformers 會形成一條處理鏈。它們將會按照它們的排列順序起作用。

public abstract class Transformer {

  /**

   * The input is a row of data and the output has to be a new row.

   *

   * @param context The current context

   * @param row     A row of data

   * @return The changed data. It must be a Map if it returns

   *         only one row or if there are multiple rows to be returned it must

   *         be a List>

   */

  public abstract Object transformRow(Map row, Context context);

}

Context 是一個抽象的類,它提供上下文關係,這可能在處理數據的時候要用到。

另外,類Foo,可以選擇不不實現這個抽象類,而只需要下面這個方法

public Object transformRow(Map row)

So there is no compile-time dependency on the DataImportHandler API

它的配置是靈活的。它允許用戶向標籤entity和field提供任意的屬性。tool將會讀取數據,並將它傳給實現類。如果Transformer需要額外的的信息,它可以從context中取得。

正則表達式轉換器

tool它提供了一個內嵌的轉換器,叫做正則表達式轉換器。它可以使用正則表達式從原數據中解析出我們想要的值。org.apache.solr.handler.dataimport.RegexTransformer 是它的名字. 因爲它屬於默認的包,所以它的包名是可以被忽略的。

例子: 

<entity name="foo" transformer="RegexTransformer"  

query="select full_name , emailids from foo"/>

... />

   <field column="full_name"/>

   <field column="firstName" regex="Mr(/w*)/b.*" sourceColName="full_name"/>

   <field column="lastName" regex="Mr.*?/b(/w*)" sourceColName="full_name"/>

   <field column="mailId" splitBy="," sourceColName="emailids"/>

</entity>

 

屬性

RegexTransfromer只對屬性中有regex或者splitBy的域起作用。所有的屬性我們列在下面。

  • regex : 這是要匹配的正則表達式。regex和splitBy兩者必有其一。如果沒有,這個域將不會被正則表達式轉換器處理。

  • sourceColName : 正則表達式起作用的列。. 如果這個這個屬性不存在,那麼source將等同域target。

  • splitBy : 如果正則表達式,是被用來分割一個字符串以獲得多個值,那麼使用這個。

  • replaceWith : 跟 屬性regex一起使用。相當於我們平常使用的方法new String().replaceAll(, )

這裏,屬性‘regex’和‘sourceColName’是轉換器自定義的屬性。它從resultSet中讀取域‘full_name’的值,然後轉換它,並將結果分別傳給‘firstName’和‘lastName’。所以,儘管查詢結果只返回一列“full_name”,但solr document依然可以獲得額外的兩個域“firstName”和‘lastName’。

域'emailids'  是一個用逗號分隔着的值。 所以,我們最終可以從emailids得到一個以上的emial id。mailid 在solr中應該被定義爲多值的。

腳本轉換器

你可以使用javascript 或者其他的 腳本語言來寫轉換器,只要java支持這種腳本。在這裏我們應該使用java 6.

<dataConfig>
        <script><![CDATA[
                function f1(row)        {
                    row.put('message', 'Hello World!');
                    return row;
                }
        ]]></script>
        <document>
                <entity name="e" pk="id" transformer="script:f1" query="select * from X">
                ....
                </entity>
        </document>
</dataConfig>

 

  • 你可以在dataConfig結點中設置script 標籤。默認的語言是javascript。你當然可以使用另外一種語言,你可以通過script標籤中的屬性language去設置它。(必須有java6的支持)。

  • 你可以寫任意多的轉換函數。每個函數必須接受一個相當於 Map的row變量,然後要返回一個row。(轉換以後)

  • 通過在實體中指定 transformer=“script:”來使一個實體使用腳本函數。

  • 在上面的data-config中,對於結果中返回的實體e的每一個行,javascript函數都將被執行一次。 

  • 執行機制跟一個java的轉換器是一樣的。在Transformer 中有兩個參數 (transformRow(Map,Context ))。在javascript中,第二個參數被忽略了,但它一樣是起作用的。

日期格式轉換器

這裏有一個內嵌的轉換器,叫做DateFormatTransformer(日期格式轉換器) ,這個在將字符型時間轉換成java.util.Date的類型的時候是很有用的。

<field column="date" xpath="/RDF/item/date" dateTimeFormat="yyyy-MM-dd'T'hh:mm:ss" />

屬性

日期格式轉換器只對帶有屬性“dateTimeFormat”的域才起作用。其他屬性如下所示。

  • dateTimeFormat : 轉換使用的格式。這個必須服從java的SimpleDateformat。

  • sourceColName : 要使用日期轉換的列。如果沒有設定這個值,那麼源列跟目標域的名稱是一樣的。

上面的域的定義在RSS例子中有使用,以轉換RSS種子項中的時間格式。

數字格式轉換器

能將一個字符串轉換成一個數字,使用的是java中類NumberFormat。例子:

<field column="price" formatStyle="number" />

默認情況下,類Numberformat使用系統的本地格式去轉換一個字符串,如果你需要指定一個不同的本地類型的話,你可以像下面這樣指定。例子:

<field column="price" formatStyle="number" locale="de-DE" />
屬性

數字格式轉換器 只對那些帶有屬性“formatStyle”的域有用。

  • formatStyle : 解析這個域所需要的格式。這個屬性的值必須是(number|percent|integer|currency)中的一個。可以參考 java DataImport - 航夢 - 火星?地球? NumberFormat.

  • sourceColName : 要使用數字轉換的列。如果沒有設定這個值,那麼源列跟目標域的名稱是一樣的。

  • locale : 要轉換的字符串所使用的國際化格式。如果沒有設定這個值,它的默認值是系統的國際化格式。它的值必須是language-country。例如 en-US。

模板轉換器

使用DataImportHandler中強大的模板引擎來創建或者設定一個域的值。例如:

<entity name="e" transformer="TemplateTransformer" ..>

<field column="namedesc" template="hello${e.name},${eparent.surname}" />
...
</entity>

這裏模板的規則跟‘query’、‘url’的規則是一樣的。它主要能幫我們將多個值連到一起,或者忘域值注入其他的字符。這個轉換器只對擁有屬性‘template’的域起作用。

屬性
  • template : 模板字符串。上面的例子中有兩個佔位符,‘${e.name}和${eparent.surname}’。 In the above example there are two placeholders '${e.name}' and '${eparent.surname}' . 兩個值都必須存在,否則這個模板將不會起作用。

自定義模板轉換器

如果你需要在將數據送給solr之前,對數據進行一些處理,你可以寫一個你自己的轉換器。讓我們來看一個例子。在我們的schema中我們有一個單值的域叫做‘artistName’,類型是String。這個域的值包含了多個單詞,例如‘Celine Dion’,這裏有一個問題 ,這個值包含一些開頭空格和結尾空格,這些空格不是我們想要的。solr的WhitespaceAnalyze在這裏用不上,因爲,我們並不想把這個字符串切詞了。一個可以選擇的解決方案就是自己寫一個TrimTransformer。

一個簡單的TrimTransformer

package foo;

public class TrimTransformer    {
        public Object transformRow(Map row)     {
                String artist = row.get("artist");
                if (artist != null)             
                        row.put("ar", artist.trim());
                return row;
        }
}

不需要去繼承任何類。這個類只需要有transformRow 方法,就像上面的那樣。DataImportHandler會自動辨別它,並使用反射機制來調用它。你可以在你的data-config.xml文件中這樣來設置:

<entity name="artist" query="..." transformer="foo.TrimTransformer">

        <field column="artistName" />

</entity>



一個通用的TrimTransformer

假設,你想寫一個通用的TrimTransformer,這樣你就不用將要處理的列寫在的代碼裏面。這裏,我們需要在data-config.xml中設一個標記來表示這個域是否要應用這個轉換器。

<entity name="artist" query="..." transformer="foo.TrimTransformer">
        <field column="artistName" trim="true" />
</entity>

現在,你需要去繼承 Transformer 這個抽象類,並使用Context中的API來獲得實體中的域,並獲得域中的屬性,檢查標記有沒有被設值。

package foo;

public class TrimTransformer extends Transformer        {
        public Map transformRow(Map row, Context context) {
                List> fields = context.getAllEntityFields();
                for (Map field : fields) {
                        // Check if this field has trim="true" specified in the data-config.xml
                        String trim = field.get("trim");
                        if ("true".equals(trim))        {
                                // Apply trim on this fied
                                String columnName = field.get("column");
                                // Get this field's value from the current row
                                String value = row.get(columnName);
                                // Trim and put the updated value back in the current row
                                if (value != null)
                                        row.put(columnName, value.trim());
                        }
                }
                return row;
        }
}

如果域是多值的,那麼返回值將會是一個list而不是單單一個對象,而且需要被恰當的處理。你可以將DataImprotHandler打包成一個jar包,然後再擴展Transformer和Context。

EntityProcessor(實體處理器)

默認的情況下,每個實體都會被sqlEntityProcessor處理。在系統 使用RDBMS作爲數據源的時候,它很適用。對於其他的數據源,例如 REST 或者不是sql的數據源 ,你可以選擇 繼承org.apache.solr.handler.dataimport.Entityprocessor. 這個抽象類。它被設計成從實體中一行一行的讀取數據。最簡單的實現自己的實體處理器的方式是 繼承EntityProcessorBase ,然後重寫方法 public Map nextRow()method。 'EntityProcessor'依賴於 數據源來獲取數據。數據源的返回類型對實體處理器來說是很重要的。下面是一些內嵌的實體處理器。

SqlEntityProcessor

它是默認的,數據源必須是DataSource類型的,在這裏默認的情況下使用的是jdbcDataSource。

XPathEntityProcessor

處理XML類型的數據源。數據源的類型必須是DataSource類型的,這種類型的數據源有HttpDataSource和FileDatasource類型。

FileListEntityProcessor

簡單的處理器,它能夠從文件系統中得到文件的集合。這個系統基於一些標準,它不使用數據源,下面是實體的屬性:

  • fileName :(必須) 辨別文件的正則表達式

  • baseDir : (必須) 根目錄(虛擬路徑)

  • recursive : 是否要遞歸的獲取文件,默認是false。

  • excludes : 匹配文件名的正則表達式

  • newerThan : 一個數字參數 . 使用格式 (yyyy-MM-dd HH:mm:ss) . 它可以是一個datemath 類型的字符串,例如:('NOW-3DAYS'). 需要加單引號。它也可以是一個變量,像${var.name}這樣。

  • olderThan : 一個數字參數 . 跟上一條的規則是一樣的

  • rootEntity :根實體的值必須是false,除非你想索引文件名。位置直接在下面的是根實體,這就意味着根實體產生的行都將被當成一個document存放在lucene裏面。但是,在這個例子裏面,我們並不想爲每個文件建立一個 document,我們想對x實體產生的行建立document,因爲實體f的屬性rootEntiry等於false,所以在直接位於實體f下面的實體將成爲根實體,它所產生的行將會被當成一個document。

  • dataSource :它必須被設爲null值,因爲這裏並不需要使用任何的數據源,即是說,我們將不會創建Datasource的實例。(在大多數的情況下,只有一個數據源,jdbc數據源,所有的實體都用,在這裏,數據源是沒有必要的。)

例子:

<dataConfig>
    <dataSource type="FileDataSource" />
    <document>
        <entity name="f" processor="FileListEntityProcessor" fileName=".*xml" newerThan="'NOW-3DAYS'" recursive="true" rootEntity="false" dataSource="null">
            <entity name="x" processor="XPathEntityProcessor" forEach="/the/record/xpath" url="${f.fileAbsolutePath}">
                <field column="full_name" xpath="/field/xpath"/> 
            </entity>
        </entity>
    <document>
<dataConfig>

千萬要注意rootEntiry這個屬性,由這個處理器所產生的域有fileAbsolutePath,fileSize,fileLastModified,fileName.

CachedSqlEntityProcessor

應該說,這是SqlEntityProcessor的一個擴展,這個處理器通過緩存一些行,來減少數據庫查詢。它幾乎對根實體沒有用,因爲這個實體中只有一個sql語句被執行了。

Example 1.

<entity name="x" query="select * from x">
    <entity name="y" query="select * from y where xid=${x.id}" processor="CachedSqlEntityProcessor">
    </entity>
<entity>

這個例子的用法跟下面的是一樣的,一個查詢被執行完,它的結果被存儲起來,下次這個查詢再被執行的的時候,它將會從緩存中取出結果並返回。

Example 2:

<entity name="x" query="select * from x">
    <entity name="y" query="select * from y" processor="CachedSqlEntityProcessor"  where="xid=x.id">
    </entity>
<entity>

這個例子跟前一個的區別在於屬性‘where’。這個例子中,查詢語句將從表中取回所有的數據,並把他們都放在緩存中。其中的關鍵就在域 屬性‘where’。緩存使用y中的xid作爲鍵值,實體被查詢的時候x.id的值就會被計算出來,我們首先會在緩存中找匹配的數據,接着返回。

 

在屬性where中,=號之前的值是y中的列,=號之後的值是計算出來的要在緩存中查找的值。

DataSource(數據源)

 org.apache.solr.handler.dataimport.DataSource 能被繼承。

public abstract class DataSource {
  /**

   * Initializes the DataSource with the Context
 and

   * initialization properties.

   * 

* This is invoked by the DataImporter after creating an * instance of this class. * * @param context * @param initProps */ public abstract void init(Context context, Properties initProps); /** * Get records for the given query.The return type depends on the * implementation . * * @param query The query string. It can be a SQL for JdbcDataSource or a URL * for HttpDataSource or a file location for FileDataSource or a custom * format for your own custom DataSource. * @return Depends on the implementation. For instance JdbcDataSource returns * an Iterator> */ public abstract T getData(String query); /** * Cleans up resources of this DataSource after use. */ public abstract void close(); }

 它必須在數據源的定義部分被配置。

<dataSource type="com.foo.FooDataSource" prop1="hello"/>


JdbcdataSource

這個是默認的,它的聲明如下:

public class JdbcDataSource extends DataSource >>

 

它可以一條一條的遍歷數據庫,每一行數據被當作一個Map。

HttpDataSource

XPathEntityProcessor使用這個數據源 . 它的聲明如下:

public class HttpDataSource extends DataSource

FileDataSource

這個很像HttpDataSource . 它的聲明如下:

public class FileDataSource extends DataSource  

The attributes are:

  • basePath: (可選的)  ,得到所需要的值時必須的基本路徑。

  • encoding: (可選的)當文件編碼跟平臺編碼不一樣的時候,應當設定這個值。

Boosting , Skipping documents(提高文檔的得分,或者跳過文檔)

我們還可以在運行的時候提高一個文檔的得分,或者跳過某一個特定的文檔。

可以通過自定義轉化器,增加一個屬性,並將它設爲true,這樣就可以跳過這個文檔了。可以通過,增加一個屬性docBoost ,屬性是文檔的評分的這種方式給文檔打分。Write a custom Transformer to add a value $skipDocwith a value 'true' to skip that document. To boost a document with a given value add $docBoost with the boost value

在 solrconfig.xml中增加數據源

我們也可以在solrconfig.xml中配置數據源,屬性是一樣的,只是方式稍微有點不同。 

     
    
      <requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
    <lst name="defaults">
      <str name="config">/home/username/data-config.xml</str>
      <lst name="datasource">
         <str name="driver">com.mysql.jdbc.Driver</str>
         <str name="url">jdbc:mysql://localhost/dbname</str>
         <str name="user">db_username</str>
         <str name="password">db_password</str>
      </lst>
    </lst>
  </requestHandler>

結構圖

下面的這個圖顯示了一般的配置文件的邏輯流程。

DataImport - 航夢 - 火星?地球?

上面的這個圖表達了這樣的一個意思:一共有三個數據源,兩個關係數據庫的數據源,和一個http/xml的數據源。

 

         jdbc1 和jdbc2 是JdbcDataSource ,它配置在solrconfig.xml文件中。

  • http是一個HttpDataSource類型的數據源。

  • 根實體是一個叫做a的表,它使用jdbc1作爲它的數據源。實體一般都與表名相同。

  • 實體A有兩個子實體 B 和C 。B使用http數據源,C使用jdbc2數據源。

  • 在執行一個full-import的命令的時候,根實體A會首先被執行。

  • 由實體A導出的每一行,都會被傳給實體B和實體C。

  • B和C通過佔位符來使用實體A中的數據。佔位符:${A.a}。

    • B 有一個url屬性

    • C 有一個query屬性

  • C 有兩個轉換器 ‘f’和‘g’。

  • 由C產生的每一行數據,都會被有序的傳給 'f '和‘g’(轉換器是鏈式的,即有序的)。每個轉換器都能夠改變輸入的值。在這裏轉換器‘g’將從一行數據(f(c .1))中產生兩行數據。 

  • 最近將每個實體的結果合併成爲一個文檔。

    • 請注意:從C產生的中間結果,例如C.1 c.2 ,f(c.1) f(c.2),都將被忽略掉。

域聲明

域的聲明,能夠幫助我們通過提供一些額外的信息得到那些不能自動獲取到的值。它依賴於結果集中的列。在dataConfig裏面配置的域,一般情況下應該跟schema配置的一樣。它應該自動繼承schema.xml中的所有的域。但是,你不能增加一些額外的域。  那麼,什麼時候增加域聲明呢?

  • 當實體處理器所產生的域的名字,跟相應的域在schema.xml中的名字不一樣的時候。

  • 當內嵌的轉換器需要一些額外的信息來決定哪個域要處理,以及該怎麼處理的時候。

  • XPathEntityprocessor 或者其他的處理器,顯示的要求一些額外的信息的時候。

關於行(row)和多值域

行在DataimportHandler中的表現形式是一個Map。在這個map裏面,key是域的名字,value可以任何一個合法的solr 類型。value也能夠是合法的solr類型的聚集(這將會映射到一個多值域)。如果數據源是RDBMS的話,一般是不會產生多值域的。當然我們可以通過加一個子實體的方式來產生多值域。這裏子實體返回的多個域,相當於父實體的一個多值域。如果數據源是xml的話,產生多值域是一件相當簡單的事情。

變量

變量是指最終代替那些佔位符的值。這是一個多級的map,每一個命名空間都是一個map,命名空間使用.分隔。例如 佔位符 ${item.ID}, 'item'是一個命名空間(也是一個map),ID是這個命名空間下的一個值。我們很容易推導出 佔位符 ${item.x.ID} 這裏x是另外一個map。變量的值能夠從Context中獲得,也可以在RDMS的query屬性中或者http數據源的url屬性中使用類似${}的佔位符獲得。

使用函數來自定義query和url的格式

 命名空間這個概念在這裏也是相當的有用的。用戶可能想要傳一個經過計算的值給 query或者url,比如這裏有一個Data類型的數據,但是你的數據源只支持另外一種格式的數據源。我們提供了一些函數,或許它們能夠幫你完成一些事情。

  • formatDate : 它可以像這樣去使用,'${dataimporter.functions.formatDate(item.ID, yyyy-MM-dd HH:mm)}' 。它的第一個參數是一個合法的變量,第二個參數是一種時間格式(這裏使用的格式工具是SimpledateFormat),The first argument can be a valid value from the VariableResolver and the second cvalue can be a a format string (use SimpledateFormat) . 它可以是一個經過計算的值,它使用solr的時間表示方式。(要注意,它必須被單引號括起來

  • escapeSql : 使用它可以對特別的sql 字符串進行包裝。例子 :'${dataimporter.functions.escapeSql(item.ID)}'. 這裏只使用一個參數,這個參數必須是一個合法的VaraiableResolver.

  • encodeUrl : 使用這個對url進行編碼。例子e: '${dataimporter.functions.encodeUrl(item.ID)}' . 只使用一個參數,這個參數必須是一個合法的VariableResolver

訪問請求參數

我們可以使用'request'命名空間來訪問傳遞給http 請求的參數。例如'${dataimporter.request.command}' 將會返回被執行的命令。任何參數都可以通過這種方式得到。

交互式的開發模式Interactive Development Mode

這是一個很酷的,並且功能強大的工具。它能夠幫助你通過圖形界面來建立一個dataconfig.xml文檔。你可以通過DataImport - 航夢 - 火星?地球? http://host:port/solr/admin/dataimport.jsp 來訪問它。 以下是它的特性:

  • 這個界面有兩個板塊,RHS是用來獲取輸入的,LHS是用來顯示輸出的。

  • 當你點擊debug now 按鈕的時候,它將會執行配置文件,並且顯示結果文檔。

  • 你可以通過start和rows這兩個參數來調試 類似從115開始到118這樣的文檔。

  • 選擇 'verbose'選項表示你想要得到一些關於中間步驟的信息。包括query產生的數據,傳給轉換器的數據,以及轉換器產生的數據。

  • 如果在運行過程中發生了異常,那麼LHS板塊將顯示異常信息。

  • fields是由實體產生的。當域沒有在schema.xml中聲明,也沒有在dataConfig.xml有聲明的時候,轉換器就不會對該域進行處理了。

屏幕快照

DataImport - 航夢 - 火星?地球?

哪裏可以找到它?

DataimportHandler是solr的新加的特性。

  • 從 DataImport - 航夢 - 火星?地球? Solr website 下載一個最新的版本 。

  • 通過 Full Import 的例子來感受一下。

在Solr JIRA.的 DataImport - 航夢 - 火星?地球? SOLR-469 你可以查看到有關DataImporthandler的一些開發討論。


第三部分:SOLR的db-data-config.xml高級進階(處理CLOB和BLOB)

我們在使用solr處理數據庫時,很多時候需要處理一下數據庫中的CLOB、BLOB字段,對於這兩種字段如何處理,下面以代碼的形式給大家演示,(不用寫Java代碼啊)

1)定義數據源

 

Code-java代碼  收藏代碼
  1. <dataSource name=<span class="code-quote">"ora"</span> driver=<span class="code-quote">"oracle.jdbc.OracleDriver"</span> url=<span class="code-quote">"...."</span> />  
  2. <span style="color: #ff0000;"><datasource name=<span class="code-quote">"ds-BlobField"</span> type=<span class="code-quote">"FieldStreamDataSource"</span> /></span>  

 

2.)寫一個blob字段處理

 

Code-java代碼  收藏代碼
  1. <entity dataSource=<span class="code-quote">"ora"</span> name=<span class="code-quote">"meta"</span> query=<span class="code-quote">"select id, filename,content, bytes from documents"</span> <span style="color: #3333ff;"><strong style="background-color: #ffffff;">transformer="ClobTransformer"</strong></span>>              
  2.            <field column=<span class="code-quote">"ID"</span> name=<span class="code-quote">"id"</span> />  
  3.            <field column=<span class="code-quote">"FILENAME"</span> name=<span class="code-quote">"filename"</span> />  
  4.            <strong><span style="color: #3333ff;"><field column="CONTENT" name="CONTENT" clob="true" /></span></strong>  
                <entity dataSource="ds-BlobField" processor="TikaEntityProcessor" url="FILE_CONTENT"
                    dataField="ATTACH.FILE_CONTENT">
                    <field column="text" name="FJ_FILE_CONTENT" /><!-- 全局搜索 -->
                    <field column="Author" name="FJ_FILE_AUTHOR" meta="true" />
                </entity>

 

 

這裏簡單介紹一下,上述藍色字體是處理clob必須的,紅色字體是處理blob必須的。

 

還是比較簡單的吧。如果你還沒看明白,,我也沒轍了。哦,這裏需要說明一下,使用上述代碼需要依賴幾個jar包:

tika-app-0.9.jar(巨大20M,不過非常好用,對於PDF、Excel、Word、PPT、RTF、TAR 、ZIP 等等吧,好多自己查吧。)

http://apache.etoak.com//pdfbox/1.6.0/pdfbox-app-1.6.0.jar

activation-1.1.jar

mail-1.4.1.jar

缺少了就跑不起來了,;)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章