Update Handler を使用したインデックス作成
更新ハンドラーは、インデックスにドキュメントを追加、削除、更新するように設計されたリクエストハンドラーです。リッチドキュメントをインポートするプラグイン(Solr Cell と Apache Tika を使用したインデックス作成を参照)に加えて、Solr は XML、CSV、および JSON で構造化されたドキュメントのインデックス作成をネイティブにサポートしています。
リクエストハンドラーを設定および使用する推奨方法は、リクエスト URL のパスにマップされるパスベースの名前を使用することです。ただし、requestDispatcher
が適切に設定されている場合、リクエストハンドラーは qt
(クエリタイプ) パラメーターを使用して指定することもできます。異なるデフォルトオプションのセットを指定したい場合に便利なように、複数の名前を使用して同じハンドラーにアクセスすることができます。
単一の統合更新リクエストハンドラーは、XML、CSV、JSON、および javabin 更新リクエストをサポートし、ContentStream の Content-Type
に基づいて適切な ContentStreamLoader
に委譲します。
ドキュメントをロードした後、インデックスが作成される前 (またはスキーマに対してチェックされる前) に前処理する必要がある場合、Solr には 更新リクエストプロセッサーと呼ばれる更新リクエストハンドラー用のドキュメント前処理プラグインがあり、デフォルトおよびカスタム設定チェーンを可能にします。
UpdateRequestHandler の設定
デフォルトの設定ファイルには、更新リクエストハンドラーがデフォルトで設定されています。
<requestHandler name="/update" class="solr.UpdateRequestHandler" />
XML 形式のインデックス更新
インデックス更新コマンドは、Content-type: application/xml
または Content-type: text/xml
を使用して、XML メッセージとして更新ハンドラーに送信できます。
ドキュメントの追加
ドキュメントを追加するための更新ハンドラーで認識される XML スキーマは非常に簡単です。
-
<add>
要素は、追加する 1 つ以上のドキュメントを導入します。 -
<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>
add コマンドは、指定可能ないくつかのオプションの属性をサポートしています。
commitWithin
-
オプション
デフォルト: なし
指定されたミリ秒数以内にドキュメントを追加します。
overwrite
-
オプション
デフォルト:
true
一意のキー制約をチェックして、同じドキュメントの以前のバージョンを上書きするかどうかを示します (下記参照)。
ドキュメントスキーマが一意キーを定義している場合、デフォルトでは、ドキュメントを追加する/update
操作は、同じ一意キーを持つインデックス内のドキュメントを上書き(つまり、置き換え)します。一意キーが定義されていない場合、既存のドキュメントを置き換えるためのチェックを行う必要がないため、インデックス作成のパフォーマンスが若干向上します。
一意キーフィールドがあるものの、一意性チェックを安全にバイパスできると確信できる場合(たとえば、インデックスをバッチで構築し、インデックス作成コードが同じドキュメントを複数回追加しないことを保証する場合)、ドキュメントを追加する際にoverwrite="false"
オプションを指定できます。
XML更新コマンド
更新中のコミットと最適化
<commit>
操作は、最後のコミット以降にロードされたすべてのドキュメントをディスク上の一または複数のセグメントファイルに書き込みます。コミットが発行されるまで、新しくインデックス付けされたコンテンツは検索に表示されません。コミット操作は新しい検索者を開き、構成されているイベントリスナーをトリガーします。
コミットは、<commit/>
メッセージで明示的に発行できます。また、solrconfig.xml
の<autocommit>
パラメータからトリガーすることもできます。
<optimize>
操作は、Solrに内部データ構造のマージを要求します。大規模なインデックスの場合、最適化の完了には時間がかかりますが、多数の小さなセグメントファイルを大きなセグメントにマージすることで、検索パフォーマンスが向上する可能性があります。Solrのレプリケーションメカニズムを使用して多数のシステムに検索を分散する場合は、最適化後にインデックス全体を転送する必要があることに注意してください。
最適化は、静的インデックス、つまり、定期的な更新プロセスの一部として最適化できるインデックス(たとえば、1日1回の更新)でのみ使用を検討する必要があります。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"/>
削除操作
ドキュメントは、2つの方法でインデックスから削除できます。「IDによる削除」は、指定されたIDを持つドキュメントを削除し、スキーマでUniqueIDフィールドが定義されている場合にのみ使用できます。子/ネストされたドキュメントでは機能しません。「クエリによる削除」は、指定されたクエリに一致するすべてのドキュメントを削除しますが、クエリによる削除ではcommitWithin
は無視されます。単一の削除メッセージに複数の削除操作を含めることができます。
<delete>
<id>0002166313</id>
<id>0031745983</id>
<query>subject:sport</query>
<query>publisher:penguin</query>
</delete>
クエリによる削除でJoinクエリパーサーを使用する場合は、 |
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
全体をメモリにロードしてからサーバーに投稿します。これは、数ギガバイトのファイルを扱う場合に問題になる可能性があります。この代替のcurl
コマンドは、同等の操作を実行しますが、curl
のメモリ使用量を最小限に抑えます。
curl https://127.0.0.1:8983/solr/my_collection/update -H "Content-Type: text/xml" -T "myfile.xml" -X POST
HTTP GETコマンドを使用して短いリクエストを送信することもできます。solrconfig.xml
のrequestParsers
要素で有効になっている場合は、以下のように、リクエストを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インデックス更新を変換する
スクリプトモジュールは、<tr>
パラメータを使用してXSL変換を適用することで、任意のXMLをインデックス付けできる個別のXSLT更新リクエストハンドラーを提供します。着信データを予期される<add><doc/></add>
形式に変換できるXSLTスタイルシートが、configsetのconf/xslt
ディレクトリに必要です。また、tr
パラメータを使用して、そのスタイルシートの名前を指定する必要があります。
この機能を使用する前に、スクリプトモジュールを有効にする必要があります。
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更新の例
標準のSolr XML出力をSolrが予期する<add><doc/></add>
形式に変換するためのsample_techproducts_configs/conf/xslt/updateXml.xsl
XSLファイルを次に示します。
<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構文に変換します。使用例の1つは、別のSolrファイルにインデックスを付けることができる形式に、Solr 1.3インデックス(CSVレスポンスライターがない)をコピーすることです(すべてのフィールドが保存されている場合)。
$ 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
JSON形式の更新リクエストは、Content-Type: application/json
またはContent-Type: text/json
を使用して、Solrの/update
ハンドラーに送信できます。
JSON形式の更新は、以下で詳しく説明するように、3つの基本的な形式を取ることができます。
-
単一のドキュメント。最上位のJSONオブジェクトとして表現されます。コマンドのセットと区別するために、
json.command=false
リクエストパラメータが必要です。 -
ドキュメントのリスト。ドキュメントごとにJSONオブジェクトを含む最上位のJSON配列として表現されます。
-
更新コマンドのシーケンス。最上位のJSONオブジェクト(マップ)として表現されます。
単一の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オブジェクトの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更新ハンドラーがサポートするすべての更新コマンドを、簡単なマッピングを通じてサポートしています。複数のコマンド、ドキュメントの追加と削除を1つのメッセージに含めることができます。
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 | クエリによる削除 |
他の更新ハンドラーと同様に、commit
、commitWithin
、optimize
、およびoverwrite
などのパラメータは、メッセージの本文ではなく、URLで指定できます。
JSON更新形式では、IDによる簡単な削除が可能です。delete
の値には、削除する特定のドキュメントIDのリスト(範囲ではない)がゼロ個以上含まれる配列を指定できます。たとえば、単一のドキュメント
{ "delete":"myid" }
またはドキュメントIDのリスト
{ "delete":["id1","id2"] }
注: IDによる削除は、子/ネストされたドキュメントでは機能しません。
各「削除」で_version_
を指定することもできます。
{
"delete":"id":50,
"_version_":12345
}
更新リクエストの本文で削除のバージョンを指定することもできます。
JSON更新の便利なパス
/update
ハンドラーに加えて、Solrにはデフォルトで利用可能なJSON固有の追加のリクエストハンドラーパスがいくつかあり、一部のリクエストパラメータの動作を暗黙的にオーバーライドします。
パス | デフォルトパラメータ |
---|---|
|
|
|
|
/update/json
パスは、Content-Type の設定が難しいアプリケーションから JSON 形式の更新コマンドを送信するクライアントにとって便利な場合があります。一方、/update/json/docs
パスは、完全な JSON コマンド構文を気にすることなく、ドキュメントを個別にまたはリストとして常に送信したいクライアントにとって特に便利です。
カスタム JSON ドキュメント
Solr はカスタム JSON をサポートできます。これについては、「カスタム JSON の変換とインデックス作成」のセクションで説明します。
CSV 形式のインデックス更新
CSV 形式の更新リクエストは、Content-Type: application/csv
または Content-Type: text/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=true
またはtrim=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:right
またはf.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