コアの結合

Solrドキュメントの結合の要件。

DSE Searchでは、1つのカスタム実装によるOS Solrクエリー時結合をサポートしています。異なるSolrコアを保持するドキュメントを含む、複数のSolrドキュメントを以下の条件下で結合できます。
  • Solrコアは、同じキースペースと同じCassandraパーティション・キーを持っている必要がある。
  • 結合するSolrコアをサポートするCassandraテーブルは両方とも、Thrift互換またはCQL互換のいずれかに揃える必要がある。一方がThrift互換で他方がCQL互換にはできない。
  • ユニーク・キー(パーティション・キーのCassandraキー・バリデーター)のタイプが同じである。
  • テーブル・パーティション・キーおよびスキーマのユニーク・キーの順序が同じである。

DataStax Enterprise 4.5以降では、4.0.2など、それ以前のバージョンのDataStax EnterpriseよりDocValues値ベースの結合が高速になっています。以前のバージョンでは、次のセクションに示した簡略化された構文を使用して結合クエリーを行う場合、CQL Solrコアのインデックスを再作成する必要がありますが、Thrift Solrコアのインデックスはその必要がありません。DataStax Enterpriseでは、CQL Solrコアの場合、簡略化された構文を使用すると、結合が自動的に高速化されます。Thrift Solrコアの場合、簡略化された構文を使用するには、インデックスを再作成し、クエリーのfromフィールドからdocValues=trueを使用します。

簡略化された構文 

Solrコアの結合には、以下の簡略化された構文を推奨します。

q={!join fromIndex=test.from}field:value

このカスタム実装により、OS Solrが必要とするto/fromパラメーターを使用する必要はなくなります。DataStax Enterpriseは、キーの構造に基づいて、パラメーターの内容を判断できます。アプリケーション、詳細度との後方互換性を確保するため、レガシー構文もサポートされています。

クエリー時結合の使用例 

この例では、songsとlyricsという2つのテーブルを作成します。これらのテーブルでは、同じパーティション・キーを使用します。songsテーブルでは、1つの単純なプライマリ・キー、つまり歌のUUIDを使用します。songsテーブルのプライマリ・キーは、そのパーティション・キーです。lyricsテーブルでは、複合プライマリ、つまりidとsongを使用します。どちらもタイプはUUIDです。複数のコアを結合した後、歌詞に"love"が含まれる歌に関する情報を取得するために、1つのクエリーをコンストラクトします。

ダウンロードしたcommands.txtファイルから、CQLコマンド、Solr HTTP要求、およびクエリーをコピーできます。

  1. この例のSolrスキーマ、Solr構成ファイル、およびコマンドを含んでいるファイルをダウンロードし解凍します。

    このアクションにより、データのインデックスを作成するためのSolr構成ファイル、/songsディレクトリーと/lyricsディレクトリー、およびスキーマが、songsテーブルとlyricsテーブルに作成されます。

  2. cqlshを起動してから、internetという名前のキースペースを作成し使用します。

    ダウンロードしたcommands.txtファイルからコピー&ペーストできます。

  3. internetキースペースを共有し、同じパーティション・キーを使用する2つのテーブル、songとlyricsを作成します。
    cqlsh> CREATE TABLE songs (song uuid PRIMARY KEY, title text, artist text);
    cqlsh> CREATE TABLE lyrics (song uuid, id uuid, words text, PRIMARY KEY (song, id));

    両方のテーブルで、songパーティション・キーであるuuidを共有します。2番目のテーブルには、idクラスター化カラムもあります。

  4. データをダウンロードしたファイルからsongsテーブルにコピーします。
  5. データをlyricsテーブルに挿入します。

    Big DataとJohn Cedrickによる歌の歌詞は、愛について書かれています。

  6. ステップ1で作成したsongsディレクトリーにナビゲートし、Solr schema.xmlを調べてみます。lyricsディレクトリーにナビゲートし、スキーマを調べてみます。スキーマにおけるユニーク・キーとlyricsテーブルのパーティション・キーの順序が、(song, id)のように同じであることに注目してください。(id, song)を使用したのでは、うまくいきません。
    <schema name="songs_schema" version="1.5">
    <types>
    <fieldType name="uuid" class="solr.UUIDField" />
    <fieldType name="text" class="solr.TextField">
    <analyzer>
    <tokenizer class="solr.StandardTokenizerFactory"/>
    </analyzer>
    </fieldType>
    </types>
    <fields>
    <field name="song" type="uuid" indexed="true" stored="true"/>
    <field name="title" type="text" indexed="true" stored="true"/>
    <field name="artist" type="text" indexed="true" stored="true"/>
    </fields>
    <defaultSearchField>artist</defaultSearchField>
    <uniqueKey>song</uniqueKey>
    </schema>
       
    <schema name="lyrics_schema" version="1.5">
    <types>
    <fieldType name="uuid" class="solr.UUIDField" />
    <fieldType name="text" class="solr.TextField">
    <analyzer>
    <tokenizer class="solr.StandardTokenizerFactory"/>
    </analyzer>
    </fieldType>
    </types>
    <fields>
    <field name="song" type="uuid" indexed="true" stored="true"/>
    <field name="id" type="uuid" indexed="true" stored="true"/>
    <field name="words" type="text" indexed="true" stored="true"/>
    </fields>
    <defaultSearchField>words</defaultSearchField>
    <uniqueKey>(song, id)</uniqueKey>
    </schema>
  7. songsディレクトリーに、internet.songsコアのolrconfig.xmlschema.xmlを送信し、internet.songsのSolrコアを作成します。
  8. lyricsディレクトリーに、internet.lyricsコアのsolrconfig.xmlschema.xmlを送信し、internet.lyricsのSolrコアを作成します。
  9. 愛に関する歌詞が含まれる歌を検索します。
    http://localhost:8983/solr/internet.songs/select/?q={!join+fromIndex=internet.lyrics}words:love&indent=true&wt=json

    出力には、歌詞に"love"という単語がある歌が2曲含まれています。1曲はBig Data、もう1曲はJohn Cedrickによる歌です。

    "response":{"numFound":2,"start":0,"docs":[
         {
    "song":"a3e64f8f-bd44-4f28-b8d9-6938726e34d4",
    "title":"Dangerous",
    "artist":"Big Data"},
         {
    "song":"8a172618-b121-4136-bb10-f665cfc469eb",
    "title":"Internet Love Song",
    "artist":"John Cedrick"}]
    }}

再帰結合のサポート 

結合クエリーをネストして、1つの結合の結果を別の結合の入力として使用し、さらにその結果を再帰的に使用できます。結合されたデータはすべて、同じパーティションに存在しなければなりません。1件のクエリーを別のSolrクエリー文字列に埋め込むには、マジック・フィールド名_query_を使用します。

以下の構文を使用して、コアを再帰的に結合するクエリーを作成します。

F1:V1 AND _query_:"{!join fromIndex=keyspace.table}(F2:V2 AND _query_:\"{!join fromIndex=keyspace.table}(F3:V3)\")"

ここで、クエリーからの最上位レベルには、ネストされた結合クエリーが含まれます。この例でのネストされた結合は、以下のとおりです。

_query_:\"{!join fromIndex=keyspace.table}(F3:V3)\"

Solrは、SQL SELECT IN ...(SELECT IN ...)クエリーと同様に、ネストされた結合クエリーを最初に実行します。その際、必要に応じて、複数のネストされた結合クエリーを有効にします。

Solr結合クエリーは、ネストされた結合クエリーからの値が結果として返される関係結合ではありません。

再帰的結合クエリーの例 

この例は、Solrクエリー時結合の例をベースにしています。AND _query_:"award:true"を使用して、"love"という単語を含む歌詞と歌を結合するクエリーに、受賞ビデオを結合する2番目のクエリーを埋め込みます。

ダウンロードしたcommands.txtファイルから、CQLコマンド、Solr HTTP要求、およびクエリーをコピーできます。
  1. cqlshで、internetキースペースを共有し、songsテーブルおよびlyricsテーブルと同じパーティション・キーを使用するvideosテーブルを作成します。
    cqlsh> CREATE TABLE videos (song uuid, award boolean, title text, PRIMARY KEY (song));

    3つのテーブルで、songパーティション・キーであるuuidを使用します。

  2. データをダウンロードしたファイルからvideosテーブルに挿入します。ビデオ・データにより、Big DataとBrad Paisleyによる歌を特集したビデオのawardフィールドがtrueに設定されます。
  3. ダウンロードしたファイルを解凍したときに作成されたvideosディレクトリーにナビゲートします。
  4. videosディレクトリーに、solrconfig.xmlschema.xmlを送信し、internet.videosのSolrコアを作成します。
  5. ネストされた結合クエリーを使用して、songsドキュメントとlyricsドキュメントをvideosドキュメントに再帰的に結合し、愛について歌いかつビデオ・アワードを受賞した歌を選択します。
    http://localhost:8983/solr/internet.songs/select/?q=
    {!join+fromIndex=internet.lyrics}words:love AND _query_:
    {!join+fromIndex=internet.videos}award:true&indent=true&wt=json

    出力は以下のようになります。

    "response":{"numFound":1,"start":0,"docs":[
        {
    "song":"a3e64f8f-bd44-4f28-b8d9-6938726e34d4",
    "title":"Dangerous",
    "artist":"Big Data"}]
    }}

レガシー結合クエリーのサポート 

DataStax Enterpriseでは、クエリーにtoフィールドとfromフィールドを含むレガシー構文の使用をサポートしています。レガシー構文を使用するための要件は、以下のとおりです。

  • テーブルで複合パーティション・キーが使用されていない。
  • mykeyspaceにあるmytable1とmytable2を結合する以下の例に示されているとおり、クエリーにforce=trueローカル・パーサー・パラメーターが含まれている。

レガシー構文の例

curl 'http://localhost:8983/solr/mykeyspace.mytable1/select/?q=\{!join+from=id+to=id+fromIndex=mykeyspace.mytable2+force=true\}'