Solr CellとApache Tikaを使用したインデックス作成
インデックスを作成する必要があるドキュメントがWord、Excel、PDFなどのバイナリ形式である場合、Solrには、Apache Tikaを使用してテキストを抽出し、Solrにインデックスを作成するリクエストハンドラが含まれています。
SolrはTikaプロジェクトのコードを使用して、Apache PDFBoxやApache POIなど、多くの異なるファイル形式パーサーをSolr自体に組み込むためのフレームワークを提供しています。
このフレームワークを使用して、SolrのExtractingRequestHandler
はTikaを内部的に使用して、データ抽出とインデックス作成のためのバイナリファイルのアップロードをサポートします。Solr Cellを使用するためにTikaをダウンロードする必要はありません。
このフレームワークが開発中だったとき、Solr *コンテンツ抽出ライブラリ*または*CEL*と呼ばれていました。その略語から、このフレームワークの名前であるSolr Cellが生まれました。Solr CellとExtractingRequestHandler
という名前はこの機能に対して同じ意味で使用されます。
Solr Cellの主要な概念
Solr Cellフレームワークを使用する場合、以下の点に注意してください。
-
Tikaは、入力ドキュメントタイプ(Word、PDF、HTMLなど)を自動的に判別し、適切にコンテンツを抽出します。必要に応じて、
stream.type
パラメータを使用してTikaのMIMEタイプを明示的に指定できます。サポートされているファイルタイプについては、http://tika.apache.org/1.28.5/formats.htmlを参照してください。 -
簡単に言うと、Tikaは内部的に、解析されたドキュメントのコアコンテンツからXHTMLドキュメントを合成することで機能します。このドキュメントは、Solr Cellによって提供される設定済みSAX ContentHandlerに渡されます。SolrはTikaのSAXイベントに応答して、コンテンツから1つ以上のテキストフィールドを作成します。Tikaは、(XHTMLとは別に)ドキュメントメタデータも公開します。
-
Tikaは、DublinCoreなどの仕様に従って、タイトル、件名、作成者などのメタデータを生成します。使用可能なメタデータは、ファイルタイプとそれらに含まれる内容に大きく依存します。作成される一般的なメタデータの一部については、以下のTikaによって作成されたメタデータセクションで説明します。Solr Cellも独自のメタデータを提供します。
-
Solr Cellは、内部XHTMLからのテキストを
content
フィールドに連結します。どの要素を含める/無視するか、どの要素を別のフィールドにマッピングするかを設定できます。 -
Solr Cellは、各メタデータ部分をフィールドにマッピングします。デフォルトでは同じ名前にマッピングされますが、いくつかのパラメータによってこの方法が制御されます。
-
Solr Cellが内部
SolrInputDocument
の作成を完了すると、残りのインデックススタックが引き継ぎます。更新ハンドラの次のステップは、更新リクエストプロセッサチェーンです。
モジュール
これは、使用する前に有効にする必要があるextraction
Solrモジュールによって提供されます。
Solrに含まれる「techproducts」の例は、Solr Cellが設定済みです。この例を使用していない場合は、以下のsolrconfig.xmlの設定セクションに注意してください。
Solr Cellのパフォーマンスへの影響
リッチドキュメント形式は、多くの場合、十分に文書化されていません。形式のドキュメントがある場合でも、ドキュメントを作成するすべての人が仕様に忠実に従うとは限りません。
これにより、できるだけ多くの形式をサポートするために細心の注意を払っていても、Tikaが正常に処理できない状況が発生する可能性があります。PDFファイルは、主にPDF形式自体が原因で、特に問題があります。
ファイルの処理に失敗した場合、ExtractingRequestHandler
には、ファイルからテキストを抽出を試みるセカンダリメカニズムがありません。例外がスローされ、失敗します。
例外によってExtractingRequestHandler
またはTikaがクラッシュした場合、リクエストハンドラはSolrが他の操作に使用するのと同じJVMで実行されているため、Solr全体もクラッシュします。
インデックス作成は、特に大規模なPDF、プレゼンテーション、またはリッチメディアが多数埋め込まれているその他のファイルでは、使用可能なSolrリソースをすべて消費する可能性もあります。
これらの理由から、Solr Cellを実稼働システムで使用することは推奨されません。
Solr Cellは、開発中に概念実証ツールとして使用し、その後、Tikaを外部プロセスとして実行して、抽出されたドキュメントをSolrに送信(SolrJ経由)してインデックスを作成することをお勧めします。このようにすることで、発生する抽出エラーはSolr自体から分離され、適切に処理できます。
これを実現する方法のいくつかの例については、Erick Ericksonによるブログ投稿「SolrJを使用したインデックス作成」を参照してください。
Solr Cellを試す
Solrに含まれているschemaless
の例を使用して、Tikaフレームワークを試すことができます。
このコマンドは、Solrを起動し、_default
設定セットを使用してgettingstarted
という名前のコア/コレクションを作成し、抽出モジュールを有効にします。そして、/update/extract
ハンドラーがgettingstarted
コア/コレクションに追加され、Solr Cellが有効になります。
bin/solr start -e schemaless -Dsolr.modules=extraction
curl -X POST -H 'Content-type:application/json' -d '{
"add-requesthandler": {
"name": "/update/extract",
"class": "solr.extraction.ExtractingRequestHandler",
"defaults":{ "lowernames": "true", "captureAttr":"true"}
}
}' 'http://localhost:8983/solr/gettingstarted/config'
Solrが起動したら、curlを使用して、HTTP POST経由でSolrに含まれているサンプルPDFを送信できます。
curl 'http://localhost:8983/solr/gettingstarted/update/extract?literal.id=doc1&commit=true' -F "myfile=@example/exampledocs/solr-word.pdf"
上記のURLは、ExtractingRequestHandler
を呼び出し、ファイルsolr-word.pdf
をアップロードし、一意のID doc1
を割り当てます。このコマンドのコンポーネントを詳しく見てみましょう。
-
literal.id=doc1
パラメーターは、インデックスが作成されるドキュメントの一意のIDを提供します。これがなければ、IDはファイルへの絶対パスに設定されます。これには、メタデータフィールドをIDにマッピングする、新しいUUIDを生成する、またはコンテンツの署名(ハッシュ)からIDを生成するなどの代替方法があります。
-
commit=true
パラメーターは、ドキュメントのインデックス作成後にSolrにコミットを実行させ、すぐに検索できるようにします。多くのドキュメントをロードする際の最適なパフォーマンスを得るには、完了するまでコミットコマンドを呼び出さないでください。 -
-F
フラグは、curlにContent-Typemultipart/form-data
を使用してデータをPOSTし、バイナリファイルのアップロードをサポートするように指示します。@
記号は、curlに添付ファイルをアップロードするように指示します。 -
引数
myfile=@example/exampledocs/solr-word.pdf
は、サンプルファイルをアップロードします。これにはパスが含まれているため、別のファイルをアップロードする場合は、必ずファイルへの相対パスまたは絶対パスを含めてください。
bin/solr post
を使用して同じことを行うこともできます。
bin/solr post -c gettingstarted example/exampledocs/solr-word.pdf -params "literal.id=doc1"
これで、http://localhost:8983/solr/gettingstarted/select?q=pdf
のようなリクエストでクエリを実行し、そのドキュメントを見つけることができます。ドキュメントは次のようになります。

このドキュメントには多くのメタデータフィールドが関連付けられていることに気付くかもしれません。Solrの構成はデフォルトで「スキーマレス」(データ駆動型)モードになっているため、抽出されたすべてのメタデータフィールドに独自のフィールドが割り当てられます。
代わりに、指定した少数のフィールドを除いて、一般的にそれらを無視したい場合があります。そのためには、uprefix
パラメータを使用して、スキーマにとって不明なメタデータフィールド名を、事実上無視されるスキーマフィールド名にマッピングします。動的フィールドignored_*
はこの目的に適しています。
マッピングするフィールドについては、fmap.IN=OUT
を使用して明示的に設定するか、スキーマでフィールドが定義されていることを確認します。次に例を示します。
bin/solr post -c gettingstarted example/exampledocs/solr-word.pdf -params "literal.id=doc1&uprefix=ignored_&fmap.last_modified=last_modified_dt"
上記の例は、ドキュメントのインデックスを1回以上作成した後に実行すると、期待どおりに機能しません。 以前は、これらのパラメータなしでドキュメントを追加したため、すべてのフィールドがその時点でインデックスに追加されました。
|
ExtractingRequestHandlerのパラメータと設定
Solr Cellのパラメータ
ExtractingRequestHandler
では、次のパラメータが使用できます。
これらのパラメータは、インデックス作成リクエストごとに(リクエストパラメータとして)設定することも、solrconfig.xml
で定義することで、リクエストハンドラーへのすべてのリクエストに対して設定することもできます。
capture
-
オプション
デフォルト:なし
指定された名前のXHTML要素を取得し、Solrドキュメントに追加します。このパラメータは、XHTMLのチャンクを別のフィールドにコピーする場合に便利です。たとえば、段落(
<p>
)を取得して別のフィールドにインデックスを作成するために使用できます。コンテンツはcontent
フィールドにも取得されます。例:
capture=p
(リクエスト内)または<str name="capture">p</str>
(solrconfig.xml
内)出力:
"p": {"これはドキュメントの段落です。"}
このパラメータは、
fmap.source_field
パラメータと組み合わせて、属性から新しいフィールドにコンテンツをマッピングすることもできます。 captureAttr
-
オプション
デフォルト:
false
Tika XHTML要素の属性を、要素の名前を付けた別のフィールドにインデックスを作成します。
true
に設定すると、HTMLから抽出する場合、Tikaは<a>
タグのhref属性を「a」という名前のフィールドとして返すことができます。例:
captureAttr=true
出力:
"div": {"classname1", "classname2"}
commitWithin
-
オプション
デフォルト:なし
指定されたミリ秒数以内にインデックスにコミットを発行します。
例:
commitWithin=10000
(10秒) defaultField
-
オプション
デフォルト:なし
uprefix
パラメータが指定されておらず、フィールドを他の方法で決定できない場合に使用されるデフォルトのフィールド。例:
defaultField=_text_
extractOnly
-
オプション
デフォルト:
false
true
の場合、ドキュメントのインデックスを作成せずに、Tikaから抽出されたコンテンツを返します。これは、抽出されたXHTMLをレスポンスで文字列として返します。画面で表示する場合、埋め込まれたXHTMLタグの表示を容易にするために、XML以外のレスポンス形式のextractFormat
パラメータを設定すると便利です。例:
extractOnly=true
extractFormat
-
オプション
デフォルト:
xml
抽出コンテンツのシリアル化形式を制御します。オプションは
xml
またはtext
です。xml
形式は実際にはXHTMLであり、Tikaコマンドラインアプリケーションに-x
コマンドを渡した場合と同じ形式ですが、テキスト形式はTikaの-t
コマンドによって生成される形式に似ています。このパラメータは、
extractOnly
がtrueに設定されている場合にのみ有効です。例:
extractFormat=text
出力:出力例(XML形式)については、https://cwiki.apache.org/confluence/display/solr/TikaExtractOnlyExampleOutputを参照してください。
fmap.source_field
-
オプション
デフォルト:なし
あるフィールド名を別のフィールド名にマッピング(移動)します。
source_field
は受信ドキュメントのフィールドである必要があり、値はマッピング先のSolrフィールドです。例:
fmap.content=text
は、Tikaによって生成されたcontent
フィールドのデータをSolrのtext
フィールドに移動します。 ignoreTikaException
-
オプション
デフォルト:なし
true
の場合、処理中に見つかった例外はスキップされます。ただし、使用可能なメタデータはインデックス化されます。例:
ignoreTikaException=true
literal.fieldname
-
オプション
デフォルト:なし
指定された値を使用して、指定された名前のフィールドに各ドキュメントの値を入力します。フィールドが複数値の場合、データは複数値にすることができます。
例:
literal.doc_status=published
出力:
"doc_status": "published"
literalsOverride
-
オプション
デフォルト:
true
true
の場合、リテラルフィールド値は、同じフィールド名を持つ他の値を上書きします。false
の場合、literal.fieldname
で定義されたリテラル値は、Tikaから抽出されたフィールドの既存のデータに追加されます。literalsOverride
をfalse
に設定する場合、フィールドは複数値である必要があります。例:
literalsOverride=false
lowernames
-
オプション
デフォルト:
false
true
の場合、すべてのフィールド名は、必要に応じてアンダースコア付きの小文字にマップされます。例:
lowernames=true
出力:「Content-Type」が入力されたとすると、ドキュメントの結果はフィールド
content_type
になります。 multipartUploadLimitInKB
-
オプション
デフォルト:
2048
キロバイト許可するドキュメントのサイズをキロバイト単位で定義します。非常に大きなドキュメントがある場合は、これを増やす必要があります。そうでない場合は拒否されます。
例:
multipartUploadLimitInKB=2048000
parseContext.config
-
オプション
デフォルト:なし
使用されているTikaパーサーがパラメータを許可している場合、パーサー構成ファイルを作成し、Solrをそれにポイントすることで、パラメータをTikaに渡すことができます。このパラメータの使用方法の詳細については、「パーサー固有のプロパティ」セクションを参照してください。
例:
parseContext.config=pdf-config.xml
passwordsFile
-
オプション
デフォルト:なし
ファイル名とパスワードのマッピングファイルのファイルパスと名前を定義します。パスワードファイルの使用方法の詳細については、「暗号化されたドキュメントのインデックス作成」セクションを参照してください。
例:
passwordsFile=/path/to/passwords.txt
resource.name
-
オプション
デフォルト:なし
インデックスを作成するファイルの名前を指定します。これはオプションですが、TikaはファイルのMIMEタイプを検出するためのヒントとして使用できます。
例:
resource.name=mydoc.doc
resource.password
-
オプション
デフォルト:なし
パスワードで保護されたPDFまたはOOXMLファイルに使用するパスワードを定義します。このパラメータの使用方法の詳細については、「暗号化されたドキュメントのインデックス作成」セクションを参照してください。
例:
resource.password=secret
tika.config
-
オプション
デフォルト:なし
カスタムTika構成ファイルのファイルパスと名前を定義します。これは、Tika実装をカスタマイズした場合にのみ必要です。
例:
tika.config=/path/to/tika.config
uprefix
-
オプション
デフォルト:なし
_スキーマで定義されていない_すべてのフィールドに、指定されたプレフィックスを付けます。これは、動的フィールド定義と組み合わせて使用すると非常に便利です。
例:
uprefix=ignored_
は、すべての不明なフィールドにプレフィックスとしてignored_
を追加します。この場合、スキーマにルールを定義して、これらのフィールドのインデックスを作成しないようにすることもできます。<dynamicField name="ignored_*" type="ignored" />
xpath
-
オプション
デフォルト:なし
抽出するときに、指定されたXPath式を満たすTika XHTMLコンテンツのみを返します。Tika XHTMLの形式の詳細については、http://tika.apache.org/1.28.5/を参照してください。解析される形式によって異なります。例については、「XPath式の定義」セクションも参照してください。
solrconfig.xmlの設定
提供されている設定セット例のいずれかを使用してSolrを起動した場合、ExtractingRequestHandler
はすでにデフォルトで設定されている可能性があります。
まず、モジュールを有効にする必要があります。 solrconfig.xml
がまだ設定されていない場合は、ExtractingRequestHandler
とその依存関係を見つけるように変更する必要があります。
<lib dir="${solr.install.dir:../../..}/modules/extraction/lib" regex=".*\.jar" />
その後、solrconfig.xml
で ExtractingRequestHandler
を設定できます。以下は、Solr の sample_techproducts_configs
configset にあるデフォルト設定で、必要に応じて変更できます。
<requestHandler name="/update/extract"
startup="lazy"
class="solr.extraction.ExtractingRequestHandler" >
<lst name="defaults">
<str name="lowernames">true</str>
<str name="fmap.content">_text_</str>
</lst>
</requestHandler>
この設定では、すべてのフィールド名は小文字に変換され(lowernames
パラメータを使用)、Tika の content
フィールドは Solr の text
フィールドにマッピングされます。
Solr Cell によって生成されたメタデータフィールドに対して、数値や日付の解析、その他の操作を行う 更新リクエストプロセッサ(URP)を設定する必要がある場合があります。 Solr の 代わりにスキーマのフィールドを明示的に定義する場合は、必要な URP を選択的に指定できます。これを指定する簡単な方法は、パラメータ
上記の推奨リストは、スキーマレスモードの一部として実行され、その機能の多くを提供する URP のリストから取得されました。ただし、スキーマにフィールドを追加する部分である |
パーサー固有のプロパティ
Tika で使用されるパーサーには、データの抽出方法を制御するための特定のプロパティがあります。これらは、特別な解析状況のために Solr を介して渡すことができます。
たとえば、Java プログラムから Tika ライブラリを使用する場合、PDFParserConfig
クラスには、垂直方向のテキストを抽出できるメソッド setSortByPosition(boolean)
があります。 ExtractingRequestHandler
を使用した設定でそのメソッドにアクセスするには、parseContext.config
プロパティを solrconfig.xml
に追加し、以下の例のように Tika の PDFParserConfig
にプロパティを設定します。
<entries>
<entry class="org.apache.tika.parser.pdf.PDFParserConfig" impl="org.apache.tika.parser.pdf.PDFParserConfig">
<property name="extractInlineImages" value="true"/>
<property name="sortByPosition" value="true"/>
</entry>
<entry>...</entry>
</entries>
このレベルの制御を必要とする特定のパーサーに設定できる構成パラメータについては、Tika Java API ドキュメントを参照してください。
暗号化されたドキュメントのインデックス作成
ExtractingRequestHandler は、リクエストの resource.password
または passwordsFile
ファイルにパスワードを指定すると、暗号化されたファイルを復号化してそのコンテンツをインデックス化します。
passwordsFile
の場合、指定されたファイルは、ルールごとに 1 行になるようにフォーマットする必要があります。各ルールには、ファイル名正規表現、その後に「=」、次に平文のパスワードが含まれています。パスワードは平文であるため、ファイルには厳格なアクセス制限が必要です。
# This is a comment
myFileName = myPassword
.*\.docx$ = myWordPassword
.*\.pdf$ = myPdfPassword
ExtractingRequestHandler の拡張
Solr で使用する独自の ContentHandler
を提供する場合は、ExtractingRequestHandler
を拡張し、createFactory()
メソッドをオーバーライドできます。このファクトリは、Tika と対話し、リテラルが Tika で解析された値をオーバーライドできるようにする SolrContentHandler
を構築する役割を担います。通常はデフォルトで true
になっているパラメータ literalsOverride
を false
に設定すると、Tika で解析された値がリテラル値に追加されます。
Solr Cell の内部
Tika によって作成されたメタデータ
前述のように、Tika はドキュメントに関するメタデータを生成します。メタデータは、作成者の名前、ページ数、ファイルサイズなど、ドキュメントのさまざまな側面を記述します。生成されるメタデータは、送信されるドキュメントの種類によって異なります。たとえば、PDF のメタデータは Word 文書のメタデータとは異なります。
Solr によって追加されたメタデータ
Tika のパーサーによって追加されたメタデータに加えて、Solr は次のメタデータを追加します
-
stream_name
:Solr にアップロードされたコンテンツストリームの名前。ファイルのアップロード方法によっては、これが設定されない場合があります。 -
stream_source_info
:ストリームに関するソース情報。 -
stream_size
:ストリームのサイズ(バイト単位)。 -
stream_content_type
:ストリームのコンテンツタイプ(使用可能な場合)。
インデックスを作成する前に extractOnly オプションを使用して、Solr がコンテンツに対してこれらのメタデータ要素に設定する値を確認することをお勧めします。 |
入力処理の順序
Solr Cell フレームワークが入力を処理する順序は次のとおりです
-
Tika はフィールドを生成するか、
literal.<fieldname>=<value>
で指定されたリテラルとして渡します。literalsOverride=false
の場合、リテラルは複数値として Tika で生成されたフィールドに追加されます。 -
lowernames=true
の場合、Tika はフィールドを小文字にマッピングします。 -
Tika は、
fmap.source=target
パラメータで指定されたマッピングルールを適用します。 -
uprefix
が指定されている場合、不明なフィールド名にはその値がプレフィックスとして付けられます。それ以外の場合は、defaultField
が指定されている場合、不明なフィールドはデフォルトフィールドにコピーされます。
Solr Cell の例
キャプチャフィールドとマッピングフィールドの使用
以下のコマンドは、<div>
タグを個別にキャプチャし(capture=div
)、そのフィールドのすべてのインスタンスを foo_t
という名前の動的フィールドにマッピングします(fmap.div=foo_t
)。
bin/solr post -c gettingstarted example/exampledocs/sample.html -params "literal.id=doc2&captureAttr=true&defaultField=_text_&fmap.div=foo_t&capture=div"
リテラルを使用してカスタムメタデータを定義する
独自のメタデータを追加するには、ファイルとともにリテラルパラメータを渡します
bin/solr post -c gettingstarted -params "literal.id=doc4&captureAttr=true&defaultField=text&capture=div&fmap.div=foo_t&literal.blah_s=Bah" example/exampledocs/sample.html
パラメータ literal.blah_s=Bah
は、すべてのドキュメントにフィールド blah_s
を挿入します。テキストのすべてのインスタンスは「Bah」になります。
XPath 式の定義
以下の例では、XPath 式を渡して、Tika によって返される XHTML を制限します
bin/solr post -c gettingstarted -params "literal.id=doc5&captureAttr=true&defaultField=text&capture=div&fmap.div=foo_t&xpath=/xhtml:html/xhtml:body/xhtml:div//node()" example/exampledocs/sample.html
インデックスを作成せずにデータを抽出する
Solr では、インデックスを作成せずにデータを抽出できます。Solr を抽出サーバーとしてのみ使用する場合、または Solr 抽出をテストする場合に、これを行うことができます。
以下の例では、extractOnly=true
パラメータを設定して、インデックスを作成せずにデータを抽出します。
curl "http://localhost:8983/solr/gettingstarted/update/extract?&extractOnly=true" --data-binary @example/exampledocs/sample.html -H 'Content-type:text/html'
出力には、読みやすくするために異なる出力形式を使用して、Tika によって生成された(そして Solr の XML によってさらにエスケープされた)XML が含まれています(-out yes
はツールに Solr の出力をコンソールにエコーするように指示します)
bin/solr post -c gettingstarted -params "extractOnly=true&wt=ruby&indent=true" -out yes example/exampledocs/sample.html
SolrJ で Solr Cell を使用する
SolrJ は、ドキュメントをインデックスに追加したり、インデックスを更新したり、インデックスをクエリしたりするために使用できる Java クライアントです。 SolrJ の詳細については、SolrJ を参照してください。
Solr Cell と SolrJ を使用して Solr インデックスにドキュメントを追加する例を次に示します。
まず、SolrJ を使用して新しい SolrClient を作成し、ContentStream(本質的にはファイルのラッパー)を含むリクエストを作成して Solr に送信します
public class SolrCellRequestDemo {
public static void main (String[] args) throws IOException, SolrServerException {
SolrClient client = new HttpSolrClient.Builder("http://localhost:8983/solr/my_collection").build();
ContentStreamUpdateRequest req = new ContentStreamUpdateRequest("/update/extract");
req.addFile(new File("my-file.pdf"));
req.setParam(ExtractingParams.EXTRACT_ONLY, "true");
NamedList<Object> result = client.request(req);
System.out.println("Result: " + result);
}
この操作は、ファイル my-file.pdf
を my_collection
の Solr インデックスにストリーミングします。
上記のサンプルコードは extract コマンドを呼び出しますが、Solr Cell でサポートされている他のコマンドに簡単に置き換えることができます。使用するキーは ContentStreamUpdateRequest
クラスで、ContentStream が正しく設定されていることを確認します。残りは SolrJ が処理します。
ContentStreamUpdateRequest
は Solr Cell に固有のものではないことに注意してください。CSV を CSV 更新ハンドラ、および更新のために Content Stream を使用する他のリクエストハンドラに送信できます。