スキーマレスモード

スキーマレスモードは、Solr の機能のセットであり、これらを一緒に使用すると、ユーザーは手動でスキーマを編集することなく、サンプルデータをインデックス作成するだけで効果的なスキーマを迅速に構築できます。

これらの Solr 機能は、すべて solrconfig.xml を介して制御され、次のとおりです。

  1. 管理スキーマ: スキーマの変更は、Solr API を介して実行時に行われます。これには、これらの変更をサポートする schemaFactory を使用する必要があります。詳細については、「スキーマファクトリ設定」セクションを参照してください。

  2. フィールド値のクラスの推測: 以前に見られなかったフィールドは、一連の値ベースのパーサーを介して実行されます。これにより、フィールド値の Java クラスが推測されます。現在、Boolean、Integer、Long、Float、Double、および Date のパーサーが利用可能です。

  3. フィールド値クラスに基づいたスキーマフィールドの自動追加: 以前に見られなかったフィールドは、フィールド値の Java クラスに基づいてスキーマに追加されます。これらは、スキーマフィールドタイプにマッピングされます。「フィールドタイプの定義とプロパティ」を参照してください。

スキーマレスの例の使用

スキーマレスモードの3つの機能は、Solr ディストリビューションの _default configset で事前に構成されています。これらの設定を使用して Solr の例のインスタンスを開始するには、次のコマンドを実行します。

bin/solr start -e schemaless

これにより、単一の Solr サーバーが起動し、初期スキーマに3つのフィールド (id_version_、および _text_) のみを含むコレクション ("gettingstarted" という名前) が自動的に作成されます。

/schema/fields スキーマ API を使用して、これを確認できます。curl https://127.0.0.1:8983/solr/gettingstarted/schema/fields は以下を出力します。

{
  "responseHeader":{
    "status":0,
    "QTime":1},
  "fields":[{
      "name":"_text_",
      "type":"text_general",
      "multiValued":true,
      "indexed":true,
      "stored":false},
    {
      "name":"_version_",
      "type":"long",
      "indexed":true,
      "stored":true},
    {
      "name":"id",
      "type":"string",
      "multiValued":false,
      "indexed":true,
      "required":true,
      "stored":true,
      "uniqueKey":true}]}

スキーマレスモードの設定

上記で説明したように、スキーマレスモードで Solr を使用するには、3つの構成要素が必要です。Solr に含まれている _default configset では、これらはすでに構成されています。ただし、独自にスキーマレスを実装する場合は、次の変更を行う必要があります。

管理スキーマの有効化

スキーマファクトリ設定」セクションで説明したように、ClassicIndexSchemaFactory を使用するように構成で指定されていない限り、管理スキーマのサポートはデフォルトで有効になっています。

ManagedIndexSchemaFactory の設定(使用するリソースファイルの制御や、将来の変更の無効化)は、下記のような明示的な <schemaFactory/> を追加することで可能です。利用可能なオプションの詳細については、スキーマファクトリーの設定 を参照してください。

<schemaFactory class="ManagedIndexSchemaFactory">
  <bool name="mutable">true</bool>
  <str name="managedSchemaResourceName">managed-schema.xml</str>
</schemaFactory>

フィールドクラスの推測を有効にする

Solrでは、UpdateRequestProcessorChain は、ドキュメントがインデックスされる前またはインデックス中に適用されるプラグインのチェーンを定義します。

Solrのスキーマレスモードのフィールド推測機能は、Solrがフィールドタイプを推測できるように特別に定義されたUpdateRequestProcessorChainを使用します。使用するデフォルトのフィールドタイプクラスを定義することもできます。

まず、次のように定義する必要があります(更新プロセッサファクトリのドキュメントについては、以下のJavadocリンクを参照してください)。

  <updateProcessor class="solr.UUIDUpdateProcessorFactory" name="uuid"/>
  <updateProcessor class="solr.RemoveBlankFieldUpdateProcessorFactory" name="remove-blank"/>
  <updateProcessor class="solr.FieldNameMutatingUpdateProcessorFactory" name="field-name-mutating"> (1)
    <str name="pattern">[^\w-\.]</str>
    <str name="replacement">_</str>
  </updateProcessor>
  <updateProcessor class="solr.ParseBooleanFieldUpdateProcessorFactory" name="parse-boolean"/> (2)
  <updateProcessor class="solr.ParseLongFieldUpdateProcessorFactory" name="parse-long"/>
  <updateProcessor class="solr.ParseDoubleFieldUpdateProcessorFactory" name="parse-double"/>
  <updateProcessor class="solr.ParseDateFieldUpdateProcessorFactory" name="parse-date">
    <arr name="format">
      <str>yyyy-MM-dd['T'[HH:mm[:ss[.SSS]]]z</str>
      <str>yyyy-MM-dd['T'[HH:mm[:ss[,SSS]]]z</str>
      <str>yyyy-MM-dd HH:mm[:ss[.SSS]]]z</str>
      <str>yyyy-MM-dd HH:mm[:ss[,SSS]]]z</str>
      <str>[EEE, ]dd MMM yyyy HH:mm[:ss] z</str>
      <str>EEEE, dd-MMM-yy HH:mm:ss z</str>
      <str>EEE MMM ppd HH:mm:ss [z ]yyyy</str>
    </arr>
  </updateProcessor>
  <updateProcessor class="solr.AddSchemaFieldsUpdateProcessorFactory" name="add-schema-fields"> (3)
    <lst name="typeMapping">
      <str name="valueClass">java.lang.String</str> (4)
      <str name="fieldType">text_general</str>
      <lst name="copyField"> (5)
        <str name="dest">*_str</str>
        <int name="maxChars">256</int>
      </lst>
      <!-- Use as default mapping instead of defaultFieldType -->
      <bool name="default">true</bool>
    </lst>
    <lst name="typeMapping">
      <str name="valueClass">java.lang.Boolean</str>
      <str name="fieldType">booleans</str>
    </lst>
    <lst name="typeMapping">
      <str name="valueClass">java.util.Date</str>
      <str name="fieldType">pdates</str>
    </lst>
    <lst name="typeMapping">
      <str name="valueClass">java.lang.Long</str> (6)
      <str name="valueClass">java.lang.Integer</str>
      <str name="fieldType">plongs</str>
    </lst>
    <lst name="typeMapping">
      <str name="valueClass">java.lang.Number</str>
      <str name="fieldType">pdoubles</str>
    </lst>
  </updateProcessor>

  <!-- The update.autoCreateFields property can be turned to false to disable schemaless mode -->
  <updateRequestProcessorChain name="add-unknown-fields-to-the-schema" default="${update.autoCreateFields:true}"
           processor="uuid,remove-blank,field-name-mutating,parse-boolean,parse-long,parse-double,parse-date,add-schema-fields"> (7)
    <processor class="solr.LogUpdateProcessorFactory"/>
    <processor class="solr.DistributedUpdateProcessorFactory"/>
    <processor class="solr.RunUpdateProcessorFactory"/>
  </updateRequestProcessorChain>

このチェーンには多くのものが定義されています。いくつか順を追って見ていきましょう。

1 まず、FieldNameMutatingUpdateProcessorFactoryを使用して、すべてのフィールド名を小文字にしています。この要素と後続のすべての<processor>要素には、nameが含まれていることに注意してください。これらの名前は、この例の最後にある最終的なチェーン定義で使用されます。
2 次に、さまざまなフィールドタイプを解析するためのいくつかの更新リクエストプロセッサを追加します。ParseDateFieldUpdateProcessorFactoryには、有効なSolrの日付として解析される可能性のある日付形式の長いリストが含まれていることに注意してください。カスタムの日付がある場合は、このリストに追加できます(詳細については、以下のJavadocへのリンクを参照してください)。
3 フィールドが解析されたら、それらのフィールドに割り当てるフィールドタイプを定義します。必要に応じてこれらを変更できます。
4 この定義では、解析ステップでフィールド内の入力データが文字列であると判断された場合、フィールドタイプtext_generalを使用してSolrのフィールドに格納します。このフィールドタイプは、デフォルトでSolrがこのフィールドでクエリを実行できるようにします。
5 text_generalフィールドを追加した後、新しいtext_generalフィールドから_strというサフィックスが付いた同じ名前のフィールドにすべてのデータをコピーするコピーフィールドルールも定義しました。これは、Solrの動的フィールド機能によって行われます。コピーフィールドルールのターゲットをこのように動的フィールドとして定義することで、スキーマで使用するフィールドタイプを制御できます。デフォルトの選択では、Solrでこれらのフィールドをファセット、ハイライト、およびソートできます。
6 これはマッピングルールの別の例です。この場合、LongまたはIntegerフィールドパーサーのいずれかがフィールドを識別した場合、両方のフィールドをplongsフィールドタイプにマッピングするように定義します。
7 最後に、プラグインのリストを呼び出すチェーン定義を追加します。これらのプラグインは、定義時に付けた名前でそれぞれ呼び出されます。ここに示すように、チェーンに他のプロセッサを追加することもできます。また、チェーン全体にname("add-unknown-fields-to-the-schema")を指定したことに注意してください。次のセクションでは、更新リクエストハンドラーがこのチェーン定義を使用するように指定するために、この名前を使用します。
このチェーン定義では、文字列フィールドに対して、対応するテキストフィールドから作成される多くのコピーフィールドルールが作成されます。データによって多くのコピーフィールドルールが作成されると、インデックス作成が著しく遅くなり、インデックスサイズが大きくなる可能性があります。これらの問題を制御するには、作成されたコピーフィールドルールを確認し、ファセット、ソート、ハイライトなどに不要なものを削除することをお勧めします。

このチェーンで使用されているクラスの詳細については、上記の更新プロセッサファクトリのJavadocへのリンクを次に示します。

デフォルトのUpdateRequestProcessorChainを設定する

UpdateRequestProcessorChainが定義されたら、インデックス更新(つまり、ドキュメントの追加、削除、置換)を行う際に使用するようにUpdateRequestHandlerに指示する必要があります。

これを行うには2つの方法があります。上記に示した更新チェーンには、default=true属性があり、これにより、任意の更新ハンドラーに使用されます。

より明示的な代替方法は、InitParams を使用して、すべての /update リクエストハンドラーにデフォルトを設定することです。

<initParams path="/update/**">
  <lst name="defaults">
    <str name="update.chain">add-unknown-fields-to-the-schema</str>
  </lst>
</initParams>
これらの変更をすべて行った後、Solrを再起動するか、コアを再ロードする必要があります。

自動フィールド推測を無効にする

自動フィールド作成は、update.autoCreateFieldsプロパティで無効にできます。これを行うには、次のようなコマンドを使用して、bin/solr config を使用できます。

bin/solr config -c mycollection -p 8983 -action set-user-property -property update.autoCreateFields -value false

インデックスされたドキュメントの例

スキーマレスモードが有効になっている場合(手動で構成した場合でも、_default configsetを使用している場合でも)、スキーマで定義されていないフィールドを含むドキュメントは、スキーマに自動的に追加される推測されたフィールドタイプを使用してインデックスされます。

たとえば、CSVドキュメントを追加すると、値に基づいてfieldTypesが設定された未知のフィールドが追加されます。

curl "https://127.0.0.1:8983/solr/gettingstarted/update?commit=true&wt=xml" -H "Content-type:application/csv" -d '
id,Artist,Album,Released,Rating,FromDistributor,Sold
44C,Old Shews,Mead for Walking,1988-08-13,0.01,14,0'

成功を示す出力

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

スキーマ内のフィールド(curl https://127.0.0.1:8983/solr/gettingstarted/schema/fields からの出力)

{
  "responseHeader":{
    "status":0,
    "QTime":2},
  "fields":[{
      "name":"Album",
      "type":"text_general"},
    {
      "name":"Artist",
      "type":"text_general"},
    {
      "name":"FromDistributor",
      "type":"plongs"},
    {
      "name":"Rating",
      "type":"pdoubles"},
    {
      "name":"Released",
      "type":"pdates"},
    {
      "name":"Sold",
      "type":"plongs"},
    {
      "name":"_root_", ...},
    {
      "name":"_text_", ...},
    {
      "name":"_version_", ...},
    {
      "name":"id", ...}
]}

さらに、テキストフィールドの文字列バージョンは、*_str動的フィールドへのcopyFieldsを使用してインデックスされます:(curl https://127.0.0.1:8983/solr/gettingstarted/schema/copyfields からの出力)

{
  "responseHeader":{
    "status":0,
    "QTime":0},
  "copyFields":[{
      "source":"Artist",
      "dest":"Artist_str",
      "maxChars":256},
    {
      "source":"Album",
      "dest":"Album_str",
      "maxChars":256}]}
明示的な指定も可能

ほとんどのフィールドでスキーマレスモードを使用したい場合でも、Schema API を使用して、それらを使用するドキュメントをインデックスする前に、明示的なタイプを使用していくつかのフィールドを事前に作成できます。

内部的には、Schema APIとスキーマレス更新プロセッサはどちらも同じ Managed Schema 機能を使用します。

また、テキストフィールドの*_strバージョンが必要ない場合は、自動生成されたスキーマからcopyField定義を削除するだけで、元のフィールドが定義されているため、再追加されることはありません。

フィールドがスキーマに追加されると、そのフィールドタイプは固定されます。その結果、以前に推測されたフィールドタイプと競合するフィールド値を持つドキュメントを追加すると失敗します。たとえば、上記のドキュメントを追加した後、"Sold"フィールドにはフィールドタイプplongsがありますが、次のドキュメントにはこのフィールドに非整数の10進数値が含まれています。

curl "https://127.0.0.1:8983/solr/gettingstarted/update?commit=true&wt=xml" -H "Content-type:application/csv" -d '
id,Description,Sold
19F,Cassettes by the pound,4.93'

このドキュメントは、この出力に示すように失敗します。

<response>
  <lst name="responseHeader">
    <int name="status">400</int>
    <int name="QTime">7</int>
  </lst>
  <lst name="error">
    <str name="msg">ERROR: [doc=19F] Error adding field 'Sold'='4.93' msg=For input string: "4.93"</str>
    <int name="code">400</int>
  </lst>
</response>