1. 程式人生 > >solr DataImportHandler (資料相關操作)

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)
  • 使用“完全匯入”命令將資料從資料庫中匯出,並提交給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

上面給出的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>


使用“增量匯入”命令

當 增量匯入被執行的時候,它讀取儲存在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 field

                                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 $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中增加資料來源

我們也可以在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的新加的特性。

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

相關推薦

solr DataImportHandler 資料相關操作

大多數的應用程式將資料儲存在關係資料庫、xml檔案中。對這樣的資料進行搜尋是很常見的應用。所謂的DataImportHandler提供一種可配置 的方式向solr匯入資料,可以一次全部匯入,也可以增量匯入。       概覽          目 標      能夠讀取關係資料庫中的資料。      

faster-rcnn 之 基於roidb get_minibatch資料準備操作

【說明】:歡迎加入:faster-rcnn 交流群 238138700,這個函式,輸入是roidb,根據roidb中給出的圖片的資訊,讀取圖片的原始檔,然後整理成blobs,供給網路訓練使用; def get_minibatch(roidb, num_classes): 這

grails項目中DB的相關操作

grails llb 項目 dpa hql post 相關 select 查詢 grails項目中(DB的相關操作) save:保存Domain對象的數據到對應的庫表中(可能是insert也可能是update) findBy: 動態方法,查找並返回第一條記錄,方法名可以變

新手小白LinuxCentos6.5部署java web項目mysql5.7安裝及相關操作

UNC cancel linux系統安裝 temporary tran sch statement current datadir 一、安裝   參考:https://dev.mysql.com/doc/refman/5.7/en/linux-installation-yu

新手小白LinuxCentos6.5部署java web項目mongodb4.0.2安裝及相關操作

read har space 創建 縮進 路徑 .org font url 紅帽企業或CentOS的Linux上安裝MongoDB的社區版: https://docs.mongodb.com/manual/tutorial/install-mongodb-on-red-ha

12c容器資料庫匯入操作_筆記Linux/oracle借用shell工具匯入資料檔案操作

Linux/oracle借用shell工具匯入資料檔案操作 一、使用shell工具,遠端連線到Linux下的oracle資料庫服務上 Xshell 6 (Build 0095) Copyright (c) 2002 NetSarang Computer, Inc. All rights reserved

系統程序的檢視相關操作及多臺主機相連進行檔案的上傳下載,遠端複製及ssh操作的應用

###系統程序及服務控制### 1.##什麼是程序   程序是指在系統中正在執行的一個應用程式 3.檢視程序 1)圖形方式檢視 gnome-system-monitor 2)程序檢視命令       ps  &nbs

Oracle資料庫DML資料操縱語言參考程式碼,簡單查詢,分組查詢,簡單增刪改操作

撰寫人——軟工二班——陳喜平 – 實驗內容: – 一、簡單查詢 – 編寫簡單查詢語句,理解笛卡爾積、選擇、投影的概念及其在SQL中的實現 –SQL PL/SQL SQLPLUS – DDL :CREATE ALTER DROP 資料定義語言 – DML INSERT DELETE UPDAT

MySQL記錄相關操作-多表查詢

一、介紹 本節主題 多表連線查詢 複合條件連線查詢 子查詢 準備表 #建表 create table department( id int, name varchar(20) ); create table employee( id int p

資料庫基礎 四張圖理解資料庫之第三張 資料庫連線 JDBC 理解 多表操作附帶相關資源第三天

JDBC JDBC: 概述: Java Data Base Connectivity,Java資料庫連線 就是Java程式碼操作不同資料庫(DBMS)。 JDBC就是Java定義的用來操作不同資料庫的規範,本質就是一些介面和類。

資料庫-DML資料操作語言和DQL資料查詢語言

MySQL的儲存引擎 什麼是儲存引擎? 關係資料庫表是用於儲存和組織資訊的資料結構,可以將表理解為由行和列組成的表格,類似於Excel的電子表格的形式。有的表簡單,有的表複雜,有的表根本不用來儲存任何長期的資料,有的表讀取時非常快,但是插入資料時很差;而我們在實際開發過程

JAVA學習之類與物件例題分享兩點確定直線並進行相關操作

最近在自學JAVA,學到類與物件章節,分享一個自我感覺還可以的例題答案,自己編寫的,發出來希望大神們知道一二。 源程式如下: package Line_Test; public class Line_Test { public static void main(String[] a

複習前面的資料相關

什麼時候請求資料: >以前我們的資料都是寫死的,在真實的開發中,需要通過使用者的操作給使用者想要的資料   怎麼請求? 1.要麼用那5步   let xhr = new XMLHttpRequest  /* get方式請求,其實就是url的方式請求  協議+域名+埠+?+查詢資訊+h

Linux學習筆記29——Linux的許可權相關操作user、group部分相關操作

這裡跟一般的信源編碼略有一些區別,比如程式還需要有一定的可讀性,因而需要引入額外的冗餘,要不然就會像brainfuck或者花式perl一樣沒法看了。這件事可以理解為兩種效果的混合:第一,我們希望程式中不僅編碼進執行的資訊,還編進一部分設計思想,這可以看作是程式設計的額外需求;第二,我們需要程

怎麼在delphi中讀取Excel資料各種詳細操作

( 一 ) 使用動態建立的方法首先建立 Excel 物件,使用ComObj :VarExcelApp : Variant ;ExcelApp := CreateOleObject ( '' Excel.Application'' ) ;1 ) 顯示當前視窗:Exce

Mybatis之Oracle增刪查改示例含Date、Clob資料型別操作

oracle表結構 create table T_USERS ( ID NUMBER not null, NAME VARCHAR2(30), SEX VARCHAR2(3), BIRS DATE, MESSAGE CLOB

程序間通訊之systemV訊號量semget semop semctl相關操作

一、什麼是訊號量? 訊號量的本質就是計數器,記錄臨界資源的數目,用來協助程序同步互斥的訪問臨界資源。為什麼不在程序中定義一個全域性變數作為計數器呢?兩個程序間的地址空間是各自獨立的,各自有各自的虛擬記憶體空間。多程序之間不能看到各自程序中的全域性變數。(程序間的虛擬記憶體h

iOS開發UI篇—自定義瀑布流控制元件蘑菇街資料重新整理操作

1 // 2 // YYWaterflowView.m 3 // 06-瀑布流 4 // 5 // Created by apple on 14-7-29. 6 // Copyright (c) 2014年 wendingding. All rights reserved.

牛客網暑期ACM多校訓練營第二場J題題解隨機化演算法/平方構造法過資料/bit操作

首先將題目化為一維進行思考。則題目化簡為修改後,查詢區間內與修改的數不同的數的個數。 該題有多種做法,先講最簡單的一種: 1.先用兩個字首和儲存區間修改值和區間修改次數,則若是 該點修改值 = 該點修改次數 * 該點初始值,則很有可能施的是多次相同的肥料(即 8 = 4 

註冊文件操作

over == equal all ase input lines () gis infoFile = ‘E:/userinfo.txt‘ # \\或者/ i = 0 for i in range(3): flag = True username =