亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

使用Apache Solr對數(shù)據(jù)庫建立索引(包括處理CLO

系統(tǒng) 1637 0

http://blog.csdn.net/xzknet/article/details/6710753

?

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

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

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

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

Delta Import工作原理
查找子Entity,直到?jīng)]有為止;
執(zhí)行Entity的deltaQuery,獲取變化數(shù)據(jù)的pk;
合并子Entity parentDeltaQuery得到的pk;
針對每一個pk Row,組裝父Entity的parentDeltaQuery;
執(zhí)行parentDeltaQuery,獲取父Entity的pk;
執(zhí)行deltaImportQuery,獲取自身的數(shù)據(jù);
如果沒有deltaImportQuery,就組裝Query

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

第二部分是DataImportHandler

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

??大多數(shù)的應(yīng)用程序?qū)?shù)據(jù)存儲在關(guān)系數(shù)據(jù)庫、xml文件中。對這樣的數(shù)據(jù)進(jìn)行搜索是很常見的應(yīng)用。所謂的DataImportHandler提供一種可配置的方式向solr導(dǎo)入數(shù)據(jù),可以一次全部導(dǎo)入,也可以增量導(dǎo)入。

????? 概覽

???????? 目 標(biāo)

  • ?????能夠讀取關(guān)系數(shù)據(jù)庫中的數(shù)據(jù)。
  • ?????通過可配置的方式,能夠?qū)?shù)據(jù)庫中多列、多表的數(shù)據(jù)生成solr文檔??
  • ?????能夠通過solr文檔更新solr
  • ???? 提供 通過配置文件就能夠?qū)胨袛?shù)據(jù)的能力
  • ????? 能夠發(fā)現(xiàn)并處理 由insert、update帶來的變化(我們假定在表中有一個叫做“l(fā)ast-modified的列”)
  • ??????能夠配置 “完全導(dǎo)入”和“增量導(dǎo)入”的時間
  • ????? 讓讀取xml文件,并建立索引成為可配置。
  • ????? 能夠?qū)?其他的數(shù)據(jù)源(例如:ftp,scp,etc)或者其他格式的文檔(Json,csv)以插件的形式集成到項目中。

???????? ? 設(shè)計思路

????????? ? 這個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的實現(xiàn)。我們一共需要在兩個地方配置文件中進(jìn)行一些配置。
    
  
  • solrconfig.xml?。 data-config.xml必須在這個文件中配置,datasource也可以。不過,一般將datasource放在data-config.xml文件中。
  • data-config.xml
  1. ?
    1. ???怎樣獲取數(shù)據(jù)?(查詢語句、url等等)
    2. ? 要讀什么樣的數(shù)據(jù)(關(guān)系數(shù)據(jù)庫中的列、或者xml的域)
    3. ?? 做什么樣的處理(修改/添加/刪除)

??? ???跟關(guān)系數(shù)據(jù)庫一起使用

????????????? 下面幾個步驟是必要的.

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

?????????? 配置數(shù)據(jù)源

??????? 將dataSource標(biāo)簽直接添加到dataConfig下面,即成為dataConfig的子元素.

    
      <dataSource type="JdbcDataSource" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost/dbname" user="db_username" password="db_password"/>
    
  • ????? 數(shù)據(jù)源也可以配置在solrconfig.xml中
  • 屬性type 指定了實現(xiàn)的類型。它是可選的。默認(rèn)的實現(xiàn)是JdbcDataSource。
  • 屬性 name? 是datasources的名字,當(dāng)有多個datasources時,可以使用name屬性加以區(qū)分
  • 其他的屬性都是隨意的,根據(jù)你使用的DataSource實現(xiàn)而定。
  • 當(dāng)然 你也可以實現(xiàn)自己的DataSource。

????????? 多數(shù)據(jù)

?????一個配置文件可以配置多個數(shù)據(jù)源。增加一個dataSource元素就可以增加一個數(shù)據(jù)源了。name屬性可以區(qū)分不同的數(shù)據(jù)源。如果配置了多于一個的數(shù)據(jù)源,那么要注意將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驅(qū)動名稱
  • url(必需的):jdbc鏈接
  • user:用戶名
  • password:密碼
  • 批量大小:jdbc鏈接中的批量大小

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

配置data-config.xml

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

???data- config.xml的根元素是document。一個document元素代表了一種文檔。一個document元素中包含了一個或者多個root實 體。一個root實體包含著一些子實體,這些子實體能夠包含其他的實體。實體就是,關(guān)系數(shù)據(jù)庫上的表或者視圖。每個實體都能夠包含多個域,每個域?qū)?yīng)著數(shù) 據(jù)庫返回結(jié)果中的一列。域的名字跟列的名字默認(rèn)是一樣的。如果一個列的名字跟solr field的名字不一樣,那么屬性name就應(yīng)該要給出。其他的需要的屬性在solrschema.xml文件中配置。

??? 為了能夠從數(shù)據(jù)庫中取得想要的數(shù)據(jù),我們的設(shè)計支持標(biāo)準(zhǔn)sql規(guī)范。這使得用戶能夠使用他任何想要的sql語句。root實體是一個中心表,使用它的列可以把表連接在一起。

???? dataconfig的結(jié)構(gòu)

??? dataconfig的結(jié)構(gòu)不是一成不變的,entity和field元素中的屬性是隨意的,這主要取決于processor和transformer。

????? 以下是entity的默認(rèn)屬性

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

???? 一下是SqlEntityProcessor的屬性

  • query (required) :sql語句

  • deltaQuery : 只在“增量導(dǎo)入”中使用

  • parentDeltaQuery : 只在“增量導(dǎo)入”中使用

  • deletedPkQuery : 只在“增量導(dǎo)入”中使用

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

Commands

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

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

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

    • 這個操作執(zhí)行的時間取決于數(shù)據(jù)集的大小。

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

    • 當(dāng)“增量導(dǎo)入”被執(zhí)行時,stored timestamp這個時間戳將會被用到

    • solr的查詢在“完全導(dǎo)入”時,不是阻塞的

    • 它還有下面一些參數(shù):

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

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

      • optimize : (default 'true').?決定這個操作之后是否要優(yōu)化。

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

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

  • status :?想要知道命令執(zhí)行的狀態(tài) ,?訪問 URL http://:/solr/dataimport .它給出了關(guān)于文檔創(chuàng)建、刪除,查詢、結(jié)果獲取等等的詳細(xì)狀況。

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

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

Full Import 例子

讓我們來看下面的例子. 假設(shè)我們數(shù)據(jù)庫中的表結(jié)構(gòu)如下:

This is a relational model of the same schema that Solr currently ships with. 我們使用這個例子來為我們的DataImportHandler建data-config.xml。 我們已經(jīng)使用這個結(jié)構(gòu)在HSQLDB上建立了一個數(shù)據(jù)庫. 好,現(xiàn)在開始了, 跟著下面的步驟走:?

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

  2. 在?example-solr-home目錄, 這里有一個 solr.war . 拷貝?這個 war 文件到你的 tomcat/jetty webapps 文件夾.? 這個 war file 也包含了hsqldb的JDBC driver.?如果你想在你已經(jīng)有了的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 執(zhí)行一個“完全導(dǎo)入”

上面給出的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"讀取數(shù)據(jù). 每一項都擁有多個特性。看下面feature實體的查詢語句

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

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

   </entity> 

     
  

feature表中的外鍵item_id跟item中的主鍵連在一起從數(shù)據(jù)庫中取得該row的數(shù)據(jù)。相同地,我們將item和category連表(它們是多對多的關(guān)系)。注意,我們是怎樣使用中間表和標(biāo)準(zhǔn)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中域的名字是一樣的話,完全避免使用在實體中配置域也是可以的。當(dāng)然,如果你需要使用轉(zhuǎn)換器的話,你還是需要加上域?qū)嶓w的。

下面是一個更短的版本

    
      
        <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>


      

使用“增量導(dǎo)入”命令

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

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

Delta-Import 例子

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

看看下面的這個?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傳過來的變量,我們叫它時間戳,它指出“完全導(dǎo)入”或者“部分導(dǎo)入”的最后運行時間。你可以在data-config.xml文件中的sql的任何地方使用這個變量,它將在processing這個過程中被賦值。

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

  • 上面例子中deltaQuery 只能夠發(fā)現(xiàn)item中的更新,而不能發(fā)現(xiàn)其他表的。你可以像下面那樣在一個sql語句中指定所有的表的更新。這里要特別說明一下的就是,它的細(xì)節(jié)對于一個使用者來說是一個不錯的練習(xí)。 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 并不是一件很享受的工作,我們還是選擇其他的方法來達(dá)到這個目的

?

    <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>

   
  

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

查詢語句,為我們?nèi)〉眯枰⑺饕臄?shù)據(jù)。

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

  • parentDeltaQuery 從deltaQuery中取得當(dāng)前表中更新的行,并把這些行提交給父表。因為,當(dāng)子表中的一行發(fā)生改變時,我們需要更新它的父表的solr文檔。

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

  • 對于query語句返回的每一行,子實體的query都將被執(zhí)行一次

  • 對于deltaQuery返回的每一行,parentDeltaQuery都將被執(zhí)行。

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

?XML/HTTP Datasource使用指南

DataImportHandler 能夠幫我們?yōu)榛贖TTP的數(shù)據(jù)源建立索引. 目前支持REST/XML APIs 和RSS/ATOM Feeds.

配置HttpDataSource

HttpDataSource在dataconfig.xml中的配置看起來應(yīng)該像這樣:?

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


    

屬性:

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

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

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

  • readTimeout (可選):?默認(rèn)值是10000ms

在?data-config.xml中的配置

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

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

  • url (必需的) :? REST API要使用這個api. (能夠被模板化). 假設(shè)數(shù)據(jù)源是一個文件,那么url應(yīng)該是這個文件的位置。

  • stream (可選) : 如果xml很大,那么它應(yīng)該設(shè)為true

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

  • xsl (可選):使用xsl對xml進(jìn)行預(yù)處理。你需要提供一個文件系統(tǒng)的全路徑,或者一個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.

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

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

  • commonField :?能夠被設(shè)為 (true或者false),假設(shè)這個是true值,一旦一個記錄中有這樣的域,那么其他記錄被寫索引的時候,這個域也會跟著記錄被寫到索引里面。

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

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

HttpDataSource 例子

下載 在DB 部分中的“完全導(dǎo)入”例子,試著去體驗一下。我們將在這里例子中為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的結(jié)構(gòu)圖,它有一些頭部元素,例如title、link、subject。這些元素將分別通過xpath語法映射到source、source-link、subject這些solr域。這個種子有多個item元素,這些元素包含了真正的新聞信息。所以,我們希望做得是,為每一個item元素建立一個文檔。

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

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

transformer=DateFormatTransformer 又是什么呢?你可以看一下DateFormatTransformer有關(guān)部分。

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

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

例子: 索引 wikipedia

利用下面的data-config.xml文件可以對wikipedia的數(shù)據(jù)建立索引。從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中有關(guān)的部分如下所示:
    
      
        <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分,內(nèi)存使用量的峰值在4G左右。

使用“增量導(dǎo)入”命令

只 有SqlEntitiProcessor支持增量數(shù)據(jù)!XPathEntityProcessor還沒有實現(xiàn)它。所以,不幸運的是,現(xiàn)在還不能為“增量導(dǎo) 入”提供支持。如果你想要在XPathEntityProcessor中實現(xiàn)這些方法,你可以在EntityProcessor.java中看看這些方法 的解釋。

Extending the tool with APIs

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

Transformer

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

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

      

DataImport - 航夢 - 火星?地球? ?注意-- trasformer的值必須是一個可以使用的classname。如果class包是 'org.apache.solr.handler.dataimport' ,包名可以被忽略。solr.也是可以使用的,如果這個class在solr的一個包下的話。這個規(guī)則適應(yīng)所有的可插入的類,像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 是一個抽象的類,它提供上下文關(guān)系,這可能在處理數(shù)據(jù)的時候要用到。

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

public Object transformRow(Map row)

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

它的配置是靈活的。它允許用戶向標(biāo)簽entity和field提供任意的屬性。tool將會讀取數(shù)據(jù),并將它傳給實現(xiàn)類。如果Transformer需要額外的的信息,它可以從context中取得。

正則表達(dá)式轉(zhuǎn)換器

tool它提供了一個內(nèi)嵌的轉(zhuǎn)換器,叫做正則表達(dá)式轉(zhuǎn)換器。它可以使用正則表達(dá)式從原數(shù)據(jù)中解析出我們想要的值。 org.apache.solr.handler.dataimport.RegexTransformer 是它的名字. 因為它屬于默認(rèn)的包,所以它的包名是可以被忽略的。

例子:?

    <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 : 這是要匹配的正則表達(dá)式。regex和splitBy兩者必有其一。如果沒有,這個域?qū)⒉粫徽齽t表達(dá)式轉(zhuǎn)換器處理。

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

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

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

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

域'emailids'? 是一個用逗號分隔著的值。 所以,我們最終可以從emailids得到一個以上的emial id。mailid 在solr中應(yīng)該被定義為多值的。

腳本轉(zhuǎn)換器

你可以使用javascript 或者其他的 腳本語言來寫轉(zhuǎn)換器,只要java支持這種腳本。在這里我們應(yīng)該使用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結(jié)點中設(shè)置script 標(biāo)簽。默認(rèn)的語言是javascript。你當(dāng)然可以使用另外一種語言,你可以通過script標(biāo)簽中的屬性language去設(shè)置它。(必須有java6的支持)。

  • 你可以寫任意多的轉(zhuǎn)換函數(shù)。每個函數(shù)必須接受一個相當(dāng)于 Map的row變量,然后要返回一個row。(轉(zhuǎn)換以后)

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

  • 在上面的data-config中,對于結(jié)果中返回的實體e的每一個行,javascript函數(shù)都將被執(zhí)行一次。?

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

日期格式轉(zhuǎn)換器

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

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


  
屬性

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

  • dateTimeFormat : 轉(zhuǎn)換使用的格式。這個必須服從java的SimpleDateformat。

  • sourceColName : 要使用日期轉(zhuǎn)換的列。如果沒有設(shè)定這個值,那么源列跟目標(biāo)域的名稱是一樣的。

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

數(shù)字格式轉(zhuǎn)換器

能將一個字符串轉(zhuǎn)換成一個數(shù)字,使用的是java中類NumberFormat。例子:

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

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

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

  
屬性

數(shù)字格式轉(zhuǎn)換器 只對那些帶有屬性“formatStyle”的域有用。

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

  • sourceColName : 要使用數(shù)字轉(zhuǎn)換的列。如果沒有設(shè)定這個值,那么源列跟目標(biāo)域的名稱是一樣的。

  • locale : 要轉(zhuǎn)換的字符串所使用的國際化格式。如果沒有設(shè)定這個值,它的默認(rèn)值是系統(tǒng)的國際化格式。它的值必須是language-country。例如 en-US。

模板轉(zhuǎn)換器

使用DataImportHandler中強大的模板引擎來創(chuàng)建或者設(shè)定一個域的值。例如:

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

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

  

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

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

自定義模板轉(zhuǎn)換器

如 果你需要在將數(shù)據(jù)送給solr之前,對數(shù)據(jù)進(jìn)行一些處理,你可以寫一個你自己的轉(zhuǎn)換器。讓我們來看一個例子。在我們的schema中我們有一個單值的域叫 做‘a(chǎn)rtistName’,類型是String。這個域的值包含了多個單詞,例如‘Celine Dion’,這里有一個問題 ,這個值包含一些開頭空格和結(jié)尾空格,這些空格不是我們想要的。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會自動辨別它,并使用反射機(jī)制來調(diào)用它。你可以在你的data-config.xml文件中這樣來設(shè)置:

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

        <field column="artistName" />

</entity>




      

一個通用的TrimTransformer

假設(shè),你想寫一個通用的TrimTransformer,這樣你就不用將要處理的列寫在的代碼里面。這里,我們需要在data-config.xml中設(shè)一個標(biāo)記來表示這個域是否要應(yīng)用這個轉(zhuǎn)換器。

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

    

現(xiàn)在,你需要去繼承 Transformer ?這個抽象類,并使用Context中的API來獲得實體中的域,并獲得域中的屬性,檢查標(biāo)記有沒有被設(shè)值。

    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而不是單單一個對象,而且需要被恰當(dāng)?shù)奶幚怼D憧梢詫ataImprotHandler打包成一個jar包,然后再擴(kuò)展Transformer和Context。

EntityProcessor(實體處理器)

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

SqlEntityProcessor

它是默認(rèn)的,數(shù)據(jù)源必須是DataSource類型的,在這里默認(rèn)的情況下使用的是jdbcDataSource。

XPathEntityProcessor

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

FileListEntityProcessor

簡單的處理器,它能夠從文件系統(tǒng)中得到文件的集合。這個系統(tǒng)基于一些標(biāo)準(zhǔn),它不使用數(shù)據(jù)源,下面是實體的屬性:

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

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

  • recursive :?是否要遞歸的獲取文件,默認(rèn)是false。

  • excludes : 匹配文件名的正則表達(dá)式

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

  • olderThan :?一個數(shù)字參數(shù) . 跟上一條的規(guī)則是一樣的

  • rootEntity :根實體的值必須是false,除非你想索引文件名。位置直接在下面的是根實體,這就意味著根實體產(chǎn)生的行都將被當(dāng)成一個document存放在 lucene里面。但是,在這個例子里面,我們并不想為每個文件建立一個document,我們想對x實體產(chǎn)生的行建立document,因為實體f的屬 性rootEntiry等于false,所以在直接位于實體f下面的實體將成為根實體,它所產(chǎn)生的行將會被當(dāng)成一個document。

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

例子:

    
      
        <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這個屬性,由這個處理器所產(chǎn)生的域有 fileAbsolutePath,fileSize,fileLastModified,fileName .

CachedSqlEntityProcessor

應(yīng)該說,這是SqlEntityProcessor的一個擴(kuò)展,這個處理器通過緩存一些行,來減少數(shù)據(jù)庫查詢。它幾乎對根實體沒有用,因為這個實體中只有一個sql語句被執(zhí)行了。

Example 1.

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

      

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

Example 2:

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

      

這個例子跟前一個的區(qū)別在于屬性‘where’。這個例子中,查詢語句將從表中取回所有的數(shù)據(jù),并把他們都放 在緩存中。其中的關(guān)鍵就在域 屬性‘where’。緩存使用y中的xid作為鍵值,實體被查詢的時候x.id的值就會被計算出來,我們首先會在緩存中找匹配的數(shù)據(jù),接著返回。

?

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

DataSource(數(shù)據(jù)源)

? 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(); }

?它必須在數(shù)據(jù)源的定義部分被配置。

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


  

JdbcdataSource

這個是默認(rèn)的,它的聲明如下:

public class JdbcDataSource extends DataSource >>

?

它可以一條一條的遍歷數(shù)據(jù)庫,每一行數(shù)據(jù)被當(dāng)作一個Map。

HttpDataSource

XPathEntityProcessor使用這個數(shù)據(jù)源 . 它的聲明如下:

    
      public class HttpDataSource extends DataSource


    

FileDataSource

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

    public class FileDataSource extends DataSource  


  

The attributes are:

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

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

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

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

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

在?solrconfig.xml中增加數(shù)據(jù)源

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

?????
????
????? <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>

結(jié)構(gòu)圖

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

上面的這個圖表達(dá)了這樣的一個意思:一共有三個數(shù)據(jù)源,兩個關(guān)系數(shù)據(jù)庫的數(shù)據(jù)源,和一個http/xml的數(shù)據(jù)源。

?

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

  • http是一個HttpDataSource類型的數(shù)據(jù)源。

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

  • 實體A有兩個子實體 B 和C?。B使用http數(shù)據(jù)源,C使用jdbc2數(shù)據(jù)源。

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

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

  • B和C通過占位符來使用實體A中的數(shù)據(jù)。占位符:${A.a(chǎn)}。

    • B 有一個url屬性

    • C 有一個query屬性

  • C 有兩個轉(zhuǎn)換器 ‘f’和‘g’。

  • 由C產(chǎn)生的每一行數(shù)據(jù),都會被有序的傳給 'f '和‘g’(轉(zhuǎn)換器是鏈?zhǔn)降模从行虻?。每個轉(zhuǎn)換器都能夠改變輸入的值。在這里轉(zhuǎn)換器‘g’將從一行數(shù)據(jù)(f(c .1))中產(chǎn)生兩行數(shù)據(jù)。?

  • 最近將每個實體的結(jié)果合并成為一個文檔。

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

域聲明

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

  • 當(dāng)實體處理器所產(chǎn)生的域的名字,跟相應(yīng)的域在schema.xml中的名字不一樣的時候。

  • 當(dāng)內(nèi)嵌的轉(zhuǎn)換器需要一些額外的信息來決定哪個域要處理,以及該怎么處理的時候。

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

關(guān)于行(row)和多值域

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

變量

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

使用函數(shù)來自定義query和url的格式

?命名空間這個概念在這里也是相當(dāng)?shù)挠杏玫摹S脩艨赡芟胍獋饕粋€經(jīng)過計算的值給 query或者url,比如這里有一個Data類型的數(shù)據(jù),但是你的數(shù)據(jù)源只支持另外一種格式的數(shù)據(jù)源。我們提供了一些函數(shù),或許它們能夠幫你完成一些事情。

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

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

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

訪問請求參數(shù)

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

交互式的開發(fā)模式Interactive Development Mode

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

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

  • 當(dāng)你點擊debug now 按鈕的時候,它將會執(zhí)行配置文件,并且顯示結(jié)果文檔。

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

  • 選擇 'verbose'選項表示你想要得到一些關(guān)于中間步驟的信息。包括query產(chǎn)生的數(shù)據(jù),傳給轉(zhuǎn)換器的數(shù)據(jù),以及轉(zhuǎn)換器產(chǎn)生的數(shù)據(jù)。

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

  • fields是由實體產(chǎn)生的。當(dāng)域沒有在schema.xml中聲明,也沒有在dataConfig.xml有聲明的時候,轉(zhuǎn)換器就不會對該域進(jìn)行處理了。

屏幕快照

哪里可以找到它?

DataimportHandler是solr的新加的特性。

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

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

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


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

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

1)定義數(shù)據(jù)源

        <dataSource name=
    
      "ora"
    
    
 driver=
    
      "oracle.jdbc.OracleDriver"
    
    
 url=
    
      "...."
    
    
 />
    
    
      <datasource name=
      
        "ds-BlobField"
      
      
 type=
      
        "FieldStreamDataSource"
      
      
 />
    
  

2.)寫一個blob字段處理

     <entity dataSource=
    
      "ora"
    
    
 name=
    
      "meta"
    
    
 query=
    
      "select id, filename,content, bytes from documents"
    
    
      
        transformer="ClobTransformer"
      
    
    
>            
            <field column=
    
      "ID"
    
    
 name=
    
      "id"
    
    
 />
            <field column=
    
      "FILENAME"
    
    
 name=
    
      "filename"
    
    
 />
            
    
      
        <field column="CONTENT" name="CONTENT" clob="true" />
      
    
  

?? ??? ??? ???? <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>

     </entity>

  

這里簡單介紹一下,上述藍(lán)色字體是處理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

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

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


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 真人特级毛片免费视频 | 快播视频在线 | 免费毛片看 | 色爱区综合五月激情 | 青草视频国产 | 青青青国产在线手机免费观看 | 北岛玲日韩精品一区二区三区 | se婷婷| 久久免费在线视频 | 成人欧美视频在线看免费 | 欧美日韩在线成人 | 日韩毛片在线影视 | 久久网站免费观看 | 免费国产97久久青草 | 国产精品mm | 国产视频www | 天天看天天射天天碰 | 欧美色综合 | 日本免费毛片在线高清看 | 97人人在线观看 | 国产21区| 美女个护士一级毛片亚洲 | 亚洲已满18点击进入在线观看 | 在线 中文字幕 日韩 欧美 | 欧美午夜在线播放 | 在线亚洲精品国产波多野结衣 | 天天做天天爱夜夜大爽完整 | 国产精品www | 看免费一级片 | 日本欧美成人 | 国产精品一区三区 | 九九九九热精品免费视频 | 久久亚洲国产成人影院 | 在线观看中文字幕第一页 | 俄罗斯午夜影院 | 成 人 黄 色视频免费播放 | 四虎永久在线精品免费影视 | 国产成人青青热久免费精品 | 国产精品v| 男人手机天堂 | 国产欧美一区二区 |