使用更新處理器建立索引

更新處理器是設計用來新增、刪除和更新索引中文件的請求處理器。除了有匯入豐富文件的外掛程式(請參閱使用 Solr Cell 和 Apache Tika 建立索引)之外,Solr 原生支援索引 XML、CSV 和 JSON 格式的結構化文件。

建議配置和使用請求處理器的方式是使用基於路徑的名稱,這些名稱會對應到請求 URL 中的路徑。但是,如果 requestDispatcher 設定適當,也可以使用 qt(查詢類型)參數指定請求處理器。可以使用多個名稱存取同一個處理器,如果您想要指定不同的預設選項集,這會很有用。

單一統一的更新請求處理器支援 XML、CSV、JSON 和 javabin 更新請求,並根據 ContentStreamContent-Type 委派給適當的 ContentStreamLoader

如果您需要在載入文件之後但在建立索引之前(甚至在針對結構描述檢查之前)預先處理文件,Solr 為更新請求處理器提供了文件預處理外掛程式,稱為 更新請求處理器,它們允許預設和自訂配置鏈。

UpdateRequestHandler 設定

預設的設定檔已預設配置更新請求處理器。

<requestHandler name="/update" class="solr.UpdateRequestHandler" />

XML 格式的索引更新

可以使用 Content-type: application/xmlContent-type: text/xml,以 XML 訊息的形式將索引更新命令傳送至更新處理器。

新增文件

更新處理器為了新增文件而識別的 XML 結構描述非常簡單

  • <add> 元素引入一或多個要新增的文件。

  • <doc> 元素引入組成文件的欄位。

  • <field> 元素呈現特定欄位的內容。

例如

<add>
  <doc>
    <field name="authors">Patrick Eagar</field>
    <field name="subject">Sports</field>
    <field name="dd">796.35</field>
    <field name="numpages">128</field>
    <field name="desc"></field>
    <field name="price">12.40</field>
    <field name="title">Summer of the all-rounder: Test and championship cricket in England 1982</field>
    <field name="isbn">0002166313</field>
    <field name="yearpub">1982</field>
    <field name="publisher">Collins</field>
  </doc>
  <doc>
  ...
  </doc>
</add>

新增命令支援一些可指定的選用屬性。

commitWithin

選用

預設值:無

在指定的毫秒數內新增文件。

overwrite

選用

預設值:true

指出是否應檢查唯一鍵約束來覆寫同一文件的先前版本(請參閱下文)。

如果文件結構描述定義了唯一鍵,則依預設,新增文件的 /update 操作會覆寫 (即取代) 索引中具有相同唯一鍵的任何文件。如果未定義唯一鍵,索引效能會稍微快一些,因為無需檢查是否有現有文件需要取代。

如果您有唯一鍵欄位,但您確信可以安全地略過唯一性檢查 (例如,您以批次方式建立索引,且您的索引程式碼保證永遠不會新增同一份文件一次以上),您可以在新增文件時指定 overwrite="false" 選項。

XML 更新指令

更新期間的提交與優化

<commit> 操作會將上次提交以來載入的所有文件寫入磁碟上的一個或多個段落檔案。在發出提交之前,新索引的內容對搜尋是不可見的。提交操作會開啟一個新的搜尋器,並觸發任何已設定的事件監聽器。

提交可以透過 <commit/> 訊息明確發出,也可以從 solrconfig.xml 中的 <autocommit> 參數觸發。

<optimize> 操作會要求 Solr 合併內部資料結構。對於大型索引,優化需要一些時間才能完成,但透過將許多小型段落檔案合併為較大的段落,搜尋效能可能會有所改善。如果您使用 Solr 的複寫機制在多個系統之間分散搜尋,請注意在優化之後,需要傳輸完整的索引。

您應該只考慮在靜態索引上使用優化,也就是可以作為常規更新程序的一部分進行優化的索引(例如,每日一次更新)。需要 NRT 功能的應用程式不應使用優化。

<commit><optimize> 元素接受這些可選屬性

waitSearcher

選用

預設值:true

封鎖直到新的搜尋器開啟並註冊為主要的查詢搜尋器,使變更可見。

expungeDeletes

選用

預設值:false

合併具有超過 10% 刪除文件的段落,並在此過程中清除已刪除的文件。產生的段落將遵循 maxMergedSegmentMB。此選項僅適用於 <commit> 操作中。

expungeDeletes 比優化便宜,但同樣的警告也適用。
maxSegments

選用

預設值:無

盡最大努力將段落合併到不超過此數量的段落,但不保證能達到目標。除非有切實的證據表明優化為少量段落是有益的,否則應省略此參數並接受預設行為。此選項僅適用於 <optimize 操作。預設值為無限制,產生的段落遵循 maxMergedSegmentMB 設定。

以下是使用可選屬性的 <commit><optimize> 的範例

<commit waitSearcher="false"/>
<commit waitSearcher="false" expungeDeletes="true"/>
<optimize waitSearcher="false"/>

刪除操作

可以透過兩種方式從索引中刪除文件。「依 ID 刪除」會刪除具有指定 ID 的文件,且僅當在 schema 中定義了 UniqueID 欄位時才能使用。它不適用於子/巢狀文件。「依查詢刪除」會刪除所有符合指定查詢的文件,儘管 commitWithin 會被「依查詢刪除」忽略。單個刪除訊息可以包含多個刪除操作。

<delete>
  <id>0002166313</id>
  <id>0031745983</id>
  <query>subject:sport</query>
  <query>publisher:penguin</query>
</delete>

在「依查詢刪除」中使用 Join 查詢解析器時,您應該使用 score 參數並將值設為「none」以避免 ClassCastException。有關 score 參數的更多詳細資訊,請參閱Join 查詢解析器一節。

回滾操作

回滾命令會回滾自上次提交以來對索引進行的所有新增和刪除。它既不呼叫任何事件監聽器,也不會建立新的搜尋器。其語法很簡單:<rollback/>

群組操作

您可以透過將多個命令與周圍的 <update> 元素群組在一起,在單個 XML 檔案中張貼它們。

<update>
  <add>
    <doc><!-- doc 1 content --></doc>
  </add>
  <add>
    <doc><!-- doc 2 content --></doc>
  </add>
  <delete>
    <id>0002166313</id>
  </delete>
</update>

使用 curl 執行更新

您可以使用 curl 工具執行上述任何命令,使用其 --data-binary 選項將 XML 訊息附加到 curl 命令,並產生 HTTP POST 要求。例如

curl https://127.0.0.1:8983/solr/my_collection/update -H "Content-Type: text/xml" --data-binary '
<add>
  <doc>
    <field name="authors">Patrick Eagar</field>
    <field name="subject">Sports</field>
    <field name="dd">796.35</field>
    <field name="isbn">0002166313</field>
    <field name="yearpub">1982</field>
    <field name="publisher">Collins</field>
  </doc>
</add>'

對於張貼包含在檔案中的 XML 訊息,您可以使用替代形式

curl https://127.0.0.1:8983/solr/my_collection/update -H "Content-Type: text/xml" --data-binary @myfile.xml

上述方法運作良好,但使用 --data-binary 選項會導致 curl 在將整個 myfile.xml 張貼到伺服器之前將其載入記憶體中。在處理多 GB 檔案時,這可能會產生問題。這個替代的 curl 命令執行等效的操作,但 curl 的記憶體使用量最少

curl https://127.0.0.1:8983/solr/my_collection/update -H "Content-Type: text/xml" -T "myfile.xml" -X POST

如果已在 solrconfig.xmlrequestParsers 元素中啟用,則也可以使用 HTTP GET 命令傳送簡短的要求,並對要求進行 URL 編碼,如下所示。請注意 "<" 和 ">" 的逸出

curl https://127.0.0.1:8983/solr/my_collection/update?stream.body=%3Ccommit/%3E&wt=xml

來自 Solr 的回應會採用此處顯示的形式

<response>
  <lst name="responseHeader">
    <int name="status">0</int>
    <int name="QTime">127</int>
  </lst>
</response>

如果發生失敗,status 欄位將為非零值。

使用 XSLT 轉換 XML 索引更新

指令碼模組提供單獨的 XSLT 更新請求處理程式,允許您透過使用 <tr> 參數來應用 XSL 轉換,索引任何任意 XML。您必須在您的 configsetconf/xslt 目錄中具有一個 XSLT 樣式表,該樣式表可以將傳入的資料轉換為預期的 <add><doc/></add> 格式,並使用 tr 參數來指定該樣式表的名稱。

您需要先啟用 指令碼模組,才能使用此功能。

tr 參數

XSLT 更新請求處理程式接受 tr 參數,該參數會識別要使用的 XML 轉換。必須在 Solr 的 conf/xslt 目錄中找到轉換。

XSLT 設定

以下範例來自 Solr 發行版中的 sample_techproducts_configs configset,顯示如何設定 XSLT 更新請求處理程式。

<!--
  Changes to XSLT transforms are taken into account
  every xsltCacheLifetimeSeconds at most.
-->
<requestHandler name="/update/xslt"
                     class="solr.scripting.xslt.XSLTUpdateRequestHandler">
  <int name="xsltCacheLifetimeSeconds">5</int>
</requestHandler>

xsltCacheLifetimeSeconds 的值為 5 對於開發來說是不錯的,可以快速查看 XSLT 的變更。對於生產環境,您可能需要更高的值。

XSLT 更新範例

以下是 sample_techproducts_configs/conf/xslt/updateXml.xsl XSL 檔案,用於將標準 Solr XML 輸出轉換為 Solr 預期的 <add><doc/></add> 格式

<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
  <xsl:output media-type="text/xml" method="xml" indent="yes"/>
  <xsl:template match='/'>
    <add>
      <xsl:apply-templates select="response/result/doc"/>
    </add>
  </xsl:template>
  <!-- Ignore score (makes no sense to index) -->
  <xsl:template match="doc/*[@name='score']" priority="100"></xsl:template>
  <xsl:template match="doc">
    <xsl:variable name="pos" select="position()"/>
    <doc>
      <xsl:apply-templates>
        <xsl:with-param name="pos"><xsl:value-of select="$pos"/></xsl:with-param>
      </xsl:apply-templates>
    </doc>
  </xsl:template>
  <!-- Flatten arrays to duplicate field lines -->
  <xsl:template match="doc/arr" priority="100">
    <xsl:variable name="fn" select="@name"/>
    <xsl:for-each select="*">
      <xsl:element name="field">
        <xsl:attribute name="name"><xsl:value-of select="$fn"/></xsl:attribute>
        <xsl:value-of select="."/>
      </xsl:element>
    </xsl:for-each>
  </xsl:template>
  <xsl:template match="doc/*">
    <xsl:variable name="fn" select="@name"/>
      <xsl:element name="field">
        <xsl:attribute name="name"><xsl:value-of select="$fn"/></xsl:attribute>
      <xsl:value-of select="."/>
    </xsl:element>
  </xsl:template>
  <xsl:template match="*"/>
</xsl:stylesheet>

此樣式表會將 Solr 的 XML 搜尋結果格式轉換為 Solr 的更新 XML 語法。一個範例用法是將 Solr 1.3 索引(沒有 CSV 回應寫入器)複製為可以索引到另一個 Solr 檔案的格式(假設所有欄位都已儲存)

$ curl -o standard_solr_xml_format.xml "https://127.0.0.1:8983/solr/techproducts/select?q=ipod&fl=id,cat,name,popularity,price,score&wt=xml"

$ curl -X POST -H "Content-Type: text/xml" -d @standard_solr_xml_format.xml "https://127.0.0.1:8983/solr/techproducts/update/xslt?commit=true&tr=updateXml.xsl"
您可以使用 回應寫入器 XSLT 範例中的 tr 參數查看相反的匯出/匯入週期。

JSON 格式的索引更新

Solr 可以接受符合已定義結構的 JSON,也可以接受任意 JSON 格式的文件。如果傳送任意格式化的 JSON,則需要隨更新請求傳送一些其他參數,這些參數在轉換和索引自訂 JSON一節中說明。

Solr 樣式 JSON

可以使用 Content-Type: application/jsonContent-Type: text/json 將 JSON 格式的更新請求傳送到 Solr 的 /update 處理程式。

JSON 格式的更新可以採用 3 種基本形式,在下面會詳細說明

  • 單個文件,表示為最上層的 JSON 物件。為了將其與一組命令區分開來,需要 json.command=false 請求參數。

  • 文件清單,表示為最上層的 JSON 陣列,其中包含每個文件的 JSON 物件。

  • 一連串更新指令,表示為最上層的 JSON 物件(一個 Map)。

新增單個 JSON 文件

透過 JSON 新增文件的最簡單方法是使用 /update/json/docs 路徑,將每個文件單獨作為 JSON 物件傳送

curl -X POST -H 'Content-Type: application/json' 'https://127.0.0.1:8983/solr/my_collection/update/json/docs' --data-binary '
{
  "id": "1",
  "title": "Doc 1"
}'

新增多個 JSON 文件

可以透過 JSON 物件的 JSON 陣列一次新增多個文件,其中每個物件代表一個文件

curl -X POST -H 'Content-Type: application/json' 'https://127.0.0.1:8983/solr/my_collection/update' --data-binary '
[
  {
    "id": "1",
    "title": "Doc 1"
  },
  {
    "id": "2",
    "title": "Doc 2"
  }
]'

範例 JSON 檔案位於 example/exampledocs/books.json,其中包含您可以新增到 Solr 「techproducts」範例的物件陣列

curl 'https://127.0.0.1:8983/solr/techproducts/update?commit=true' --data-binary @example/exampledocs/books.json -H 'Content-type:application/json'

傳送 JSON 更新指令

一般來說,JSON 更新語法支援 XML 更新處理程式支援的所有更新指令,透過簡單的對應。一個訊息中可以包含多個命令,新增和刪除文件

curl -X POST -H 'Content-Type: application/json' 'https://127.0.0.1:8983/solr/my_collection/update' --data-binary '
{
  "add": {
    "doc": {
      "id": "DOC1",
      "my_field": 2.3,
      "my_multivalued_field": [ "aaa", "bbb" ]   (1)
    }
  },
  "add": {
    "commitWithin": 5000, (2)
    "overwrite": false,  (3)
    "doc": {
      "f1": "v1", (4)
      "f1": "v2"
    }
  },

  "commit": {},
  "optimize": { "waitSearcher":false },

  "delete": { "id":"ID" },  (5)
  "delete": { "query":"QUERY" } (6)
}'
1 可以使用陣列表示多值欄位
2 在 5 秒內提交此文件
3 不要檢查是否存在具有相同 uniqueKey 的文件
4 可以使用重複的鍵表示多值欄位
5 依 ID 刪除 (uniqueKey 欄位)
6 依查詢刪除

與其他更新處理程式一樣,可以在 URL 中指定 commitcommitWithinoptimizeoverwrite 等參數,而不是在訊息的主體中指定。

JSON 更新格式允許簡單的依 ID 刪除。delete 的值可以是一個陣列,其中包含要刪除的零個或多個特定文件 ID (不是範圍)。例如,單個文件

{ "delete":"myid" }

或文件 ID 清單

{ "delete":["id1","id2"] }

注意:依 ID 刪除不適用於子/巢狀文件。

您也可以為每個「delete」指定 _version_

{
  "delete":"id":50,
  "_version_":12345
}

您也可以在更新請求的主體中指定刪除的版本。

JSON 更新便利路徑

除了 /update 處理程式外,Solr 中預設還提供了一些其他特定於 JSON 的請求處理程式路徑,這些路徑會隱式覆寫某些請求參數的行為

路徑 預設參數

/update/json

stream.contentType=application/json

/update/json/docs

stream.contentType=application/json

json.command=false

/update/json 路徑對於從應用程式傳送 JSON 格式的更新指令的用戶端可能很有用,因為設定 Content-Type 很困難,而 /update/json/docs 路徑對於始終想要傳送文件(單獨或以清單形式)而無需擔心完整 JSON 命令語法的用戶端來說,可能特別方便。

自訂 JSON 文件

Solr 可以支援自訂 JSON。這在轉換和索引自訂 JSON一節中介紹。

CSV 格式的索引更新

可以使用 Content-Type: application/csvContent-Type: text/csv 將 CSV 格式的更新請求傳送到 Solr 的 /update 處理程式。

範例 CSV 檔案位於 example/exampledocs/books.csv,您可以使用它將一些文件新增到 Solr 「techproducts」範例

curl 'https://127.0.0.1:8983/solr/my_collection/update?commit=true' --data-binary @example/exampledocs/books.csv -H 'Content-type:application/csv'

CSV 更新參數

CSV 處理器允許在 URL 中以以下格式指定多個參數:f.parameter.optional_fieldname=value

下表描述了更新處理器的參數。

separator

選用

預設值:,

用作欄位分隔符號的字元。此參數為全域性;若要針對每個欄位使用,請參閱 split 參數。

範例:separator=%09

trim

選用

預設值:false

如果為 true,則移除值的前導和尾隨空白。此參數可以是全域性或針對每個欄位設定。

範例:f.isbn.trim=truetrim=false

header

選用

預設值:true

如果輸入的第一行包含欄位名稱,則設定為 true。如果缺少 fieldnames 參數,將會使用這些欄位名稱。此參數為全域性。

fieldnames

選用

預設值:無

新增文件時要使用的欄位名稱列表,以逗號分隔。此參數為全域性。

範例:fieldnames=isbn,price,title

literal.field_name

選用

預設值:無

指定欄位名稱的文字值。此參數為全域性。

範例:literal.color=red

skip

選用

預設值:無

要略過的欄位名稱列表,以逗號分隔。此參數為全域性。

範例:skip=uninteresting,shoesize

skipLines

選用

預設值:0

在 CSV 資料開始之前,要捨棄輸入串流中的行數,包括標頭(如果存在)。此參數為全域性。

範例:skipLines=5

encapsulator

選用

預設值:無

選擇性用於包圍值的字元,以保留諸如 CSV 分隔符號或空白之類的字元。這種標準 CSV 格式透過將封裝符號加倍,來處理封裝值中出現的封裝符號本身。

此參數為全域性;若要針對每個欄位使用,請參閱 split

範例:encapsulator="

escape

選用

預設值:無

用於跳脫 CSV 分隔符號或其他保留字元的字元。如果指定了跳脫字元,則除非也明確指定,否則不會使用封裝符號,因為大多數格式使用封裝或跳脫,而不是兩者都使用。

範例:escape=\

keepEmpty

選用

預設值:false

保留並索引零長度(空)欄位。此參數可以是全域性或針對每個欄位設定。

範例:f.price.keepEmpty=true

map

選用

預設值:無

將一個值對應到另一個值。格式為 map=value:replacement (可以為空)。此參數可以是全域性或針對每個欄位設定。

範例:map=left:rightf.subject.map=history:bunk

split

選用

預設值:無

如果為 true,則使用單獨的剖析器將欄位分割為多個值。此參數是針對每個欄位使用的,例如 f.FIELD_NAME_GOES_HERE.split=true

overwrite

選用

預設值:true

如果為 true,則根據 Solr 綱要中宣告的 uniqueKey 欄位,檢查並覆寫重複的文件。如果您知道要索引的文件不包含任何重複項,則將此值設定為 false 可以顯著加快速度。

此參數為全域性。

commit

選用

預設值:無

在擷取資料後發出提交。此參數為全域性。

commitWithin

選用

預設值:無

在指定的毫秒數內新增文件。此參數為全域性。

範例:commitWithin=10000

rowid

選用

預設值:無

rowid(行號)對應到參數值指定的欄位,例如,如果您的 CSV 沒有唯一索引鍵,並且您想要使用行 ID 作為唯一索引鍵。此參數為全域性。

範例:rowid=id

rowidOffset

選用

預設值:0

將給定的偏移量(作為整數)新增到 rowid,然後再將其新增到文件中。此參數為全域性。

範例:rowidOffset=10

索引索引標籤分隔的檔案

用於索引 CSV 文件的相同功能,也可以輕鬆用於索引索引標籤分隔的檔案(TSV 檔案),甚至可以處理反斜線跳脫,而不是 CSV 封裝。

例如,可以使用以下方式將 MySQL 資料表轉儲到索引標籤分隔的檔案:

SELECT * INTO OUTFILE '/tmp/result.txt' FROM mytable;

然後可以透過將 separator 設定為索引標籤 (%09) 並將 escape 設定為反斜線 (%5c),將此檔案匯入 Solr。

curl 'https://127.0.0.1:8983/solr/my_collection/update/csv?commit=true&separator=%09&escape=%5c' --data-binary @/tmp/result.txt

CSV 更新便捷路徑

除了 /update 處理器之外,Solr 中預設還有另一個 CSV 特定請求處理器路徑可用,該路徑會隱式覆寫某些請求參數的行為

路徑 預設參數

/update/csv

stream.contentType=application/csv

/update/csv 路徑可能對從應用程式傳送 CSV 格式更新命令的用戶端很有用,在這些應用程式中設定 Content-Type 會很困難。