1. schema.xmlファイルについて
Solrはデータを構造化形式でファイルシステムに保存し、インデックスを作成する際にschema.xmlファイルを使用してこの構造を定義します。
schema.xmlファイルはSolrインストールパッケージのexample/solr/collection1/conf/ディレクトリにあり、主にSolrのフィールド(Field)とフィールドタイプ(FieldType)を設定するために使用されます。
重要な注意点:
- SolrのField関連設定は使用前に設定する必要があります
- schema.xmlファイル名は変更できません
- 使用時には
SolrHome/conf/ディレクトリにあるか、Solr Webアプリケーションのクラスローダーが読み込める位置にある必要があります
ここではSolr 4.10.4バージョンのschema.xmlファイルを例として説明します。
2. schema.xmlファイルの解説
ファイル例:
<?xml version="1.0" encoding="UTF-8" ?>
<schema name="product" version="1.5">
<field name="_version_" type="long" indexed="true" stored="true"/>
<field name="_root_" type="string" indexed="true" stored="false"/>
<field name="product_id" type="string" indexed="true" stored="true" required="true" multiValued="false" />
<field name="product_name" type="text_general" indexed="true" stored="true"/>
<field name="price" type="tfloat" indexed="true" stored="true"/>
<uniqueKey>product_id</uniqueKey>
<fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
<fieldType name="string" class="solr.StrField" sortMissingLast="true" />
<fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.StandardTokenizerFactory"/>
</analyzer>
</fieldType>
</schema>
(1) ルート要素はschemaで、name属性は表示用で任意に設定できます。versionはSolrスキーマの構文とセマンティクスのバージョン番号です。Solr 4.10では1.5バージョンを使用しています。
バージョン履歴:
- 1.0バージョン:multiValued属性が存在せず、すべてのフィールドは本質的に多値です
- 1.1バージョン:multiValued属性が導入され、デフォルトはfalse
- 1.2バージョン:omitTermFreqAndPositions属性が導入され、デフォルトはtrue(テキストフィールドを除く)
- 1.3バージョン:オプションのフィールド圧縮機能が削除されました
- 1.4バージョン:autoGeneratePhraseQueries属性が導入され、単一文字列から複数のトークンを生成する際のQueryParserの動作を制御します。1.4以上のバージョンではデフォルトで無効
- 1.5バージョン:int、float、boolean、stringなどの原始フィールドタイプでは、omitNormsがデフォルトでtrue
(2) ルート要素には主にfieldとfieldTypeの2つのタグがあり、それぞれドメインとドメインタイプを定義します。
2.1 field - フィールドの設定
<field name="product_id" type="string" indexed="true" stored="true" required="true" multiValued="false" />
fieldはMySQLのテーブルフィールドに似ており、name、type(以前に定義されたfieldType)などの属性を含みます。属性の詳細は以下の通りです:
必須属性:
- name:フィールドの名前。文字またはアンダースコアで始まり、数字で始めることはできません
- type:以下で定義されるfieldTypeのタイプ
- indexed:このフィールドが検索およびソートされる必要がある場合はtrueに設定
- stored:このフィールドがクエリ時に表示される必要がある場合はtrueに設定し、元の値を保存します。検索時に元の値を表示する必要がない場合はfalseに設定し、特に値が大きいフィールドではfalseに設定します
- required:このフィールドが必須であることを示します。MySQLのnot nullと同様です。trueに設定すると、インデックス作成時にこのフィールドの値が含まれている必要があり、存在しない場合はエラーがスローされます
- multiValued:複数の値を持つかどうか(Solrでは1つのドメインに複数の値を保存できます。MySQLのユーザーが複数の友達を保存したり、商品に複数の詳細画像があるのと同様です)
オプション属性:
- docValues:現在のfieldにdocValuesという名前のfieldを追加するかどうか。facetクエリ、グループ化、ソート、functionクエリに役立ちます
- 欠点:インデックス作成プロセスが若干遅くなり、インデックスファイルが大きくなります
- 利点:インデックスデータのロードが速くなり、NRT(近リアルタイム検索)にもより親和性が高く、メモリ使用効率も向上します
- 制限:現在docValuesはstrField、UUIDField、Trie*Fieldのみをサポートしています。フィールドの値は単一値である必要があり、このfieldの値は存在するかデフォルト値を持つ必要があります
- compressed:gzip圧縮を使用するかどうか(TextFieldとStrFieldのみ圧縮可能)、デフォルトはfalse
- omitNorms(専門属性):Normを無視するかどうか。trueに設定すると、このフィールドに関連付けられたノルムを無視します(これはフィールドの長さの正規化と検索時のドキュメント重みスコアのブーストを無効にし、一部のメモリスペースを節約します)。全文テキストのfieldと検索時に重みを設定する必要があるfieldのみnormが必要です。全文テキストタイプのフィールド、または検索時に現在のフィールドの重みを設定する必要がある場合のみ、関連するノルムが必要で、その場合はfalseに設定する必要があります。デフォルトでは、原始(未分析)タイプのノルムは無視されます
- termVectors:デフォルトはfalse。trueにすると、現在のフィールドのterm vector(用語ベクトル)が保存されます。MoreLikeThisを使用する場合、類似性マッチングに使用されるfieldのstoredはtrueに設定し、パフォーマンスを向上させます
- termPositions:term vectorを使用して位置情報を保存し、保存コストを増加させます
- termOffsets:term vectorを使用してオフセット情報を保存し、保存コストを増加させます
- default:現在のフィールドのデフォルト値を設定します。ドキュメントを追加する際にこのフィールドに値が指定されていない場合、このデフォルト値が使用されます
注意事項:
- name="_version_"のフィールドは追加する必要があります。Solrドキュメントのバージョンを記録するために使用されます。このフィールドを削除する場合は、solrconfig.xmlファイルの更新ログを無効にする必要があります。そうしないと、Solrが起動しません。SolrCloudは_version_と更新ログを必要とします
- name="_root_"のフィールドは、ネストされたドキュメントブロックのルートドキュメントを指します。ネストされたドキュメントがある場合は必須です。そうしないと、ネストされたドキュメントが削除される可能性があります
- ほとんどのSolrドキュメントには
<uniqueKey>id</uniqueKey>が存在します——主キーはidです。十分な理由がない限り、idフィールドを削除しないでください。もちろん、実際のビジネスに合わせて独自の主キーを設定できます
2.2 fieldType - フィールドタイプの設定
fieldTypeはSolr内部で使用され、カスタムドメインタイプはサポートされていません。原始FieldTypeの定義例:
<fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory" />
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
<filter class="solr.LowerCaseFilterFactory" />
</analyzer>
<analyzer type="query">
<tokenizer class="solr.StandardTokenizerFactory" />
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true" />
<filter class="solr.LowerCaseFilterFactory" />
</analyzer>
</fieldType>
必須属性:
- name:ドメインタイプの名前。fieldのtypeです
- class:ドメインタイプに対応するSolrの標準Javaクラス。"Solr"で始まるclassはorg.apache.solr.analysisパッケージのJavaクラスです
- analyzer:インデックスと検索に使用するトークナイザーを定義します。**これはコア設定です——使用するアナライザーが異なれば、インデックスと検索も異なります**
- type:index(インデックスプロセス)とquery(検索プロセス)
- tokenizer:使用する具体的なトークナイザーを指定します
- filter:使用するフィルターを指定します
オプション属性:
- positionIncrementGap:multiValued="true"の場合に使用され、同じドキュメント内のこのタイプのデータの空白間隔を定義します。つまり、複数の値間の仮想空白の数を設定し、フレーズマッチングの誤りを避けます
- autoGeneratePhraseQueries:類義語検索や自動修正に似ています。例えば、"wi fi"を"wifi"や"wi-fi"に自動的に変換できます。この属性を設定しない場合は、クエリ時に強制的に引用符を付けます(例:'wi fi')
- sortMissingLast / sortMissingFirst:クエリ結果をソートする際に、このフィールドの値が存在しない場合、前面または後面に配置します。ソート条件を無視します。使用方法は以下の通り:
- デフォルト値は両方ともfalseで、Luceneの内部ソートルールを使用します:このフィールドを持たないドキュメントは昇順では最後に配置され、降順結果では最初に配置されます
- sortMissingLast="true":このフィールドをソートする際に、このフィールドを持たないドキュメントはこのフィールドを持つドキュメントの後ろに配置されます。リクエスト時のソートルール(ascまたはdesc)を無視します
- sortMissingFirst="true":sortMissingLastの作用とは逆です
一般的なドメインタイプ(class):
① solr.StrField:
<fieldType name="string" class="solr.StrField" sortMissingLast="true" />
このタイプはトークナイズされず、文字ごとにインデックス/保存されます。docValuesドメインをサポートしています。このfieldTypeのfieldにdocValuesフィールドを追加する場合、そのfieldは単一値ドメインである必要があり、そのドメインは存在するかデフォルト値を持つ必要があります。
② solr.BoolField:
<fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/>
booleanドメイン。true/falseに対応します。
③ solr.Trie*Field:デフォルトの数値ドメインタイプ:
<fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0"/>
<fieldType name="float" class="solr.TrieFloatField" precisionStep="0" positionIncrementGap="0"/>
<fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
<fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" positionIncrementGap="0"/>
これらのフィールドはdocValuesをサポートしていますが、fieldは単一値である必要があり、必須であるかデフォルト値を持つ必要があります。
④ solr.Trie*Field:より速い範囲クエリのための数値ドメインタイプ:
より速い範囲クエリが必要な場合は、tint / tfloat / tlong / tdoubleタイプを検討してください:
<fieldType name="tint" class="solr.TrieIntField" precisionStep="8" positionIncrementGap="0"/>
<fieldType name="tfloat" class="solr.TrieFloatField" precisionStep="8" positionIncrementGap="0"/>
<fieldType name="tlong" class="solr.TrieLongField" precisionStep="8" positionIncrementGap="0"/>
<fieldType name="tdouble" class="solr.TrieDoubleField" precisionStep="8" positionIncrementGap="0"/>
このタイプは**各値を異なる精度レベルでインデックス化し**、範囲の両端の間隔が大きい場合の範囲クエリを高速化します。
precisionStep:通常数値範囲クエリに使用され、その値が小さいほど(ビット単位)、インデックス時にそのドメインの値から生成されるトークンの数が多くなります⇒インデックスサイズが少し大きくなります⇒しかし、これは数値範囲検索の応答速度を速めます。
precisionStep="0"は異なる精度レベルのインデックスを無効にします。
positionIncrementGap:現在のドメインが多値ドメインの場合、複数の値間の間隔。この属性は単一値ドメインでは意味がありません。
⑤ solr.TrieDateField:日付ドメインタイプ:
<fieldType name="date" class="solr.TrieDateField" precisionStep="0" positionIncrementGap="0"/>
日付フィールドは1995-12-31T23:59:59Z形式の日付のみをサポートし、最後のZはUTC時間を示します。小数点は秒数のみ使用できます:1995-12-31T23:59:59.999Z。他の部分は必須であり、形式を変更できません。
日付式は"NOW"(現在時刻)を基準とした時間を表すこともできます:
- NOW/HOUR ⇒ 現在時間の開始に戻ります
- NOW-1DAY ⇒ 正確に前日
- NOW/DAY+6MONTHS+3DAYS ⇒ 当日から6ヶ月3日後の時刻
より速い範囲クエリと日付ファセットの要件については、tdateタイプを使用することを検討してください:
<fieldType name="tdate" class="solr.TrieDateField" precisionStep="6" positionIncrementGap="0"/>
⑥ solr.BinaryField:
<fieldtype name="binary" class="solr.BinaryField"/>
Base64エンコードされた文字列ドメインタイプ。つまり、データをBase64エンコードしてから送信/検索する必要があります。
⑦ solr.RandomSortField:
<fieldType name="random" class="solr.RandomSortField" indexed="true" />
ランダムソートドメインタイプ。データの保存や検索には使用されず、ドキュメントの擬似ランダムソートを実現するためにスキーマでこのタイプのフィールドを宣言できます。
⇒フィールド名とインデックスのバージョンに基づいてソートを生成します。インデックスのバージョン_version_が変更されず、同じフィールド名を再利用すれば、ドキュメントの順序は一貫します。
⇒同じバージョンのインデックスに対して異なる擬似ランダムドキュメントソートが必要な場合は、dynamicFieldを使用し、リクエスト中のフィールド名を変更してください。
⑧ solr.TextField:
最も多く使用されるドメインタイプで、トークナイズが必要です。通常、ユーザーはインデックスとクエリのためにカスタムアナライザーを設定する必要があります。アナライザーにはトークナイザー(tokenizer)と複数のフィルター(filter)が含まれます。例:
<!-- 空白トークナイザー、正確なマッチ:
インデックスにtextタイプのインデックスを追加する際、Solrはまず空白でトークナイズし、
その後、指定されたフィルターでトークナイズ結果を順次フィルタリングし、
最後に残った結果がインデックスに追加され、クエリに備えます。
注意:Solrのanalysisパッケージは中国語のパッケージをサポートしていません。独自の中国語トークナイザーを追加する必要があります。
-->
<fieldType name="text_ws" class="solr.TextField" positionIncrementGap="100">
<analyzer>
<tokenizer class="solr.WhitespaceTokenizerFactory" />
</analyzer>
</fieldType>
一般的なフィルター(filter):
① 分離フィルター:
<!-- トークナイズとマッチング時に"-"ハイフン、アルファベットと数字の境界、非アルファベット文字を考慮し、
これにより"wifi"や"wi fi"が"Wi-Fi"にマッチできます。
-->
<filter class="solr.WordDelimiterFilterFactory" generateWordParts="1"
generateNumberParts="1" catenateWords="1" catenateNumbers="1"
catenateAll="0" splitOnCaseChange="1" />
② 同義語フィルター:
<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt"
ignoreCase="true" expand="true" />
③ ストップワード(無効な単語)フィルター:
<!-- ストップワード(stopword)削除後、フレーズ間に間隔stopwordを追加:
つまり、インデックス作成プロセス中(インデックス作成と検索)に無視される単語、例えばis thisなどの一般的な単語。
conf/stopwords.txtファイルで設定とメンテナンスを行います。
-->
<filter class="solr.StopFilterFactory" ignoreCase="true"
words="stopwords.txt" enablePositionIncrements="true" />
2.3 copyField - コピー域の設定
Solrは複数のドメインの値を1つのドメインにコピーすることを許可し、検索を容易にします。
例えば:"Solr"を含むドキュメントを検索する必要がある場合、タイトル、要約情報、本文に"Solr"を含むドキュメントをすべて検索する必要があります。copyFieldドメインがあると、タイトル、要約情報、本文の3つのドメインの値をすべて書く必要がなく、copyFieldドメインを検索するだけで済みます。
**インデックス作成時に、Solrはソースドメインの内容をターゲットドメインにコピーします。**
<copyField source="title" dest="search_content"/>
属性の説明:
- source:ソースドメインの名前
- dest:ターゲットドメインの名前。**検索時にターゲットドメインをデフォルト検索ドメインとして指定すると、クエリ効率を向上させることができます。**
使用上の注意事項:
- **ターゲットドメインの定義では、必ずmultiValued="true"を指定する必要があります。**
- 単一のドメインのみをコピーします。コピーされるドメイン自体が多値ドメインの場合、ターゲットドメインも多値ドメインになります⇒実際の意味がありません
- 複数のドメインをコピーする場合、そのうちの1つが多値ドメインであれば、ターゲットドメインは必ず多値ドメインになります
2.4 dynamicField - 動的ドメインの設定
動的ドメインはワイルドカードを使用してドメインの曖昧一致を実現し、頻繁にschema.xmlファイルを修正するのを効果的に避けることができます。⇒ schema.xmlファイルを修正すると、Solrプログラムは設定ファイルを再ロードする必要があり、少し面倒です。
**dynamicField(動的ドメイン)とcopyField(コピー域)はSolrが拡張したドメインで、Luceneには対応する概念がありません。**
<dynamicField name="*_i" type="int" indexed="true" stored="true"/>
属性の説明:
name:動的ドメインの名前。式です:
- *は任意の文字に一致し、パターンの最前または最後にのみ出現できます
- 長いパターンが先に一致します
- 2つのパターンが同時に一致する場合、最初に定義されたものが優先されます
使用上の説明:
使用するには、ドメイン名が式と一致するだけで済みます。例えば、"product_i":"ノートパソコン"の場合、product_iを使用するだけで、他の定義は不要です。上記の一致で見つからない場合は、以下のタイプの設定を設定し、typeをStringとして扱うように定義します。通常は発生しませんが、定義しないと一致が見つからないとエラーが発生します。
<dynamicField name="*_i" type="ignored" multiValued="true"/>
2.5 uniqueKey - 一意識別子の設定
**SolrはuniqueKeyを使用してドキュメントの主キーを指定します。デフォルトではidドメインが主キーとして使用されるため、idドメインは必須です。**
**⇒もちろんユーザーは独自の主キーをカスタマイズできます。**
<uniqueKey>product_id</uniqueKey>
Solrでrequired="true"とマークされたフィールドは、
SolrはuniqueKeyで識別されたfield(デフォルトはid)に基づいて、増分インポート時に重複インポートするかどうかを決定します:idが同じ場合は重複インポートしません。
2.6 その他の設定の説明
(1) デフォルト検索ドメイン:
<defaultSearchField>search_content</defaultSearchField>
検索パラメータで特定のfieldが指定されていない場合、これはデフォルトのドメインとして検索されます。
**Solr 6.xバージョンではこのパラメータが削除されました。**
(2) Solrクエリパーサー:
<!-- Solr 6.6バージョンからdefaultOperatorはサポートされなくなりました -->
<solrQueryParser defaultOperator="OR"/>
検索パラメータのフレーズ間の論理を設定できます。ANDまたはORです。
3. schema.xmlの最適化について
3.1 fieldの設定テクニック
- 検索専用で、結果として元の値を返す必要がないfield(特に大きなfield)はすべてstored="false"に設定します
- 検索に使用する必要がなく、結果としてのみ返されるfieldはindexed="false"に設定します
- すべての不必要なcopyFieldを削除します
- インデックスフィールドを最小化し、検索効率を向上させるために、すべてのtext fieldにindex="false"を設定し、それらをすべて1つの総text fieldにコピーして、そのtext fieldを検索します
- 検索パフォーマンスを最大化するために、JavaクライアントでConcurrentUpdateSolrServerを使用してSolrと連携します(並行変更サービスを使用)
- サーバー側でJVMを実行します。つまり、-serverサーバーモードを使用し、可能な限り高いレベルのログ出力レベルを使用し、各リクエストを記録せず、ログ量を減らします
3.2 fieldの設定例
| トークナイズ | 検索 | 保存 | 例 |
|---|---|---|---|
| √ | √ | √ | ウェブページのタイトル、内容 |
| √ | X | √ | ウェブページの公開時間 |
| X | X | √ | 参照画像の位置 |
| √ | √ | √ | ウェブページタイトル、内容 |
**インデックスも必要なく、トークナイズも必要なく、保存も必要ないフィールドは存在しません。なぜなら、そのようなフィールドはLuceneでは意味がないからです。**