本トピックでは、多次元照会、ページングおよびソート付き照会、トークン化テキスト照会、あいまい検索、および集計クエリを用いて、Lindorm ワイドテーブルのデータを検索インデックスで照会する方法について説明します。
前提条件
Lindorm-cli を使用して LindormTable に接続済みである必要があります。詳細については、「Lindorm-cli を用いた LindormTable への接続と利用」をご参照ください。
テストデータを準備し、検索インデックスを作成済みである必要があります。詳細については、「検索インデックスの管理」をご参照ください。
多次元照会の実行
以下の文を実行して、多次元照会を行います。
例 1
SELECT * FROM search_table WHERE gender='M' AND city='Hangzhou' OR city='Beijing';以下の結果が返されます:
+---------+--------+-----+--------+--------------+------------------+------+ | user_id | name | age | gender | address | email | city | +---------+--------+-----+--------+--------------+------------------+------+ | 6 | Li | 32 | M | Yuhang District, Hangzhou | a***@example.net | Hangzhou | | 1 | Zhang | 18 | M | Chaoyang District, Beijing | a***@example.net | Beijing | | 20 | Wang | 28 | M | Binjiang District, Hangzhou | a***@example.net | Hangzhou | +---------+--------+-----+--------+--------------+------------------+------+例 2
SELECT * FROM search_table WHERE age > 30 AND city != 'Hangzhou';以下の結果が返されます:
+---------+--------+-----+--------+--------------+------------------+------+ | user_id | name | age | gender | address | email | city | +---------+--------+-----+--------+--------------+------------------+------+ | 28 | Chen | 36 | F | Nanshan District, Shenzhen | a***@example.net | Shenzhen | +---------+--------+-----+--------+--------------+------------------+------+
ソートおよびページング
検索インデックスは任意の列に対するソートをサポートしています。以下の文を実行して、照会結果をソートします。
SELECT * FROM search_table WHERE gender='M' ORDER BY age DESC;以下の結果が返されます:
+---------+--------+-----+--------+--------------+------------------+------+ | user_id | name | age | gender | address | email | city | +---------+--------+-----+--------+--------------+------------------+------+ | 6 | Li | 32 | M | Yuhang District, Hangzhou | a***@example.net | Hangzhou | | 20 | Wang | 28 | M | Binjiang District, Hangzhou | a***@example.net | Hangzhou | | 1 | Zhang | 18 | M | Chaoyang District, Beijing | a***@example.net | Beijing | +---------+--------+-----+--------+--------------+------------------+------+検索インデックスは、
limitまたはoffsetを用いたページングをサポートしています。以下の文を実行して、ページングクエリを行います。SELECT * FROM search_table WHERE gender='M' ORDER BY age DESC LIMIT 1,10;以下の結果が返されます:
+---------+--------+-----+--------+--------------+------------------+------+ | user_id | name | age | gender | address | email | city | +---------+--------+-----+--------+--------------+------------------+------+ | 20 | Wang | 28 | M | Binjiang District, Hangzhou | a***@example.net | Hangzhou | | 1 | Zhang | 18 | M | Chaoyang District, Beijing | a***@example.net | Beijing | +---------+--------+-----+--------+--------------+------------------+------+
あいまい検索の実行
以下の文を実行して、email 列に `example` が含まれるデータを照会します。
SELECT * FROM search_table WHERE email LIKE '%example%';以下の結果が返されます:
+---------+--------+-----+--------+--------------+------------------+------+
| user_id | name | age | gender | address | email | city |
+---------+--------+-----+--------+--------------+------------------+------+
| 1 | Zhang | 18 | M | Chaoyang District, Beijing | a***@example.net | Beijing |
| 6 | Li | 32 | M | Yuhang District, Hangzhou | a***@example.net | Hangzhou |
| 20 | Wang | 28 | M | Binjiang District, Hangzhou | a***@example.net | Hangzhou |
| 28 | Chen | 36 | F | Nanshan District, Shenzhen | a***@example.net | Shenzhen |
+---------+--------+-----+--------+--------------+------------------+------+あいまい検索のパフォーマンスは、テーブル内のデータ量に依存します。トークン化テキスト照会を代わりに実行することを推奨します。
集計および分析
検索インデックスは、COUNT、SUM、AVG、MIN、MAX などの一般的な集計関数をサポートしています。また、DISTINCT や GROUP BY もサポートしています。
city列の値がHangzhouであるレコード数をカウントするには、以下の文を実行します。SELECT COUNT(*) FROM search_table WHERE city='Hangzhou';以下の結果が返されます:
+----------+ | EXPR$0 | +----------+ | 2 | +----------+照会結果から重複する値を除外するには、以下の文を実行します。
SELECT distinct(age) FROM search_table WHERE gender='M';以下の結果が返されます:
+---------------+ | DISTINCT(age) | +---------------+ | 18 | | 28 | | 32 | +---------------+照会結果をグループ化するには、以下の文を実行します。
SELECT city,count(*) AS cnt FROM search_table WHERE gender='M' GROUP BY city ORDER BY cnt DESC;以下の結果が返されます:
+------+-----+ | city | cnt | +------+-----+ | Hangzhou | 2 | | Beijing | 1 | +------+-----+
集計クエリで WHERE 条件を指定しない場合、検索インデックスは使用されません。この場合、WHERE キーワードの前にヒントパラメーター _l_force_index_ を追加することで、検索インデックスの強制使用が可能です。詳細については、「hintOptions のパラメーター」および「例 4:クエリで _l_force_index_ を指定してインデックスを強制的に使用する」をご参照ください。
トークン化テキスト照会の実行
トークン化された列に対しては、MATCH 関数 を用いてトークン化テキスト照会を実行できます。
重要MATCH 関数は LindormTable 2.7.2 以降のバージョンでサポートされています。 LindormTable のバージョンを確認またはアップグレードするには、「LindormTable のリリースノート」および「マイナーバージョンの更新」をご参照ください。
以下の例では、
ageの値が範囲(10,30]内であり、かつaddressの値がHangzhouと一致するレコードを照会します。address列はトークン化されています。SELECT * FROM search_table WHERE age > 10 AND age <= 30 AND MATCH (address) AGAINST ('Hangzhou');以下の結果が返されます:
+---------+--------+-----+--------+--------------+------------------+------+ | user_id | name | age | gender | address | email | city | +---------+--------+-----+--------+--------------+------------------+------+ | 20 | Wang | 28 | M | Binjiang District, Hangzhou | a***@example.net | Hangzhou | +---------+--------+-----+--------+--------------+------------------+------+以下の例では、
ageの値が範囲(30,35]内であり、かつaddressの値が正確なフレーズYuhang District, Hangzhouと一致するレコードを照会します。address列はトークン化されています。SELECT * FROM search_table WHERE age > 30 AND age <= 35 AND MATCH (address) AGAINST ('"Yuhang District, Hangzhou"');以下の結果が返されます:
+---------+--------+-----+--------+--------------+------------------+------+ | user_id | name | age | gender | address | email | city | +---------+--------+-----+--------+--------------+------------------+------+ | 6 | Li | 32 | M | Yuhang District, Hangzhou | a***@example.net | Hangzhou | +---------+--------+-----+--------+--------------+------------------+------+
LindormTable 2.7.2 より前のバージョンでは、等価演算子
=を用いてトークン化テキスト照会を実行できます。重要等価演算子によるトークン化テキスト照会は非推奨です。 新しいバージョンへアップグレードし、代わりに MATCH 関数 を使用してください。LindormTable のバージョンを確認またはアップグレードするには、「LindormTable のリリースノート」および「マイナーバージョンの更新」をご参照ください。
LindormTable 2.8.2.3 以降では、新規作成される検索インデックスは等価演算子によるトークン化テキスト照会をサポートしなくなります。既存の検索インデックスは引き続きサポートされます。
以下の例では、
ageの値が範囲(10, 30]内であり、かつaddressの値がHangzhouと一致するレコードを照会します。address列はトークン化されています。SELECT * FROM search_table WHERE age > 10 AND age <= 30 AND address = 'Hangzhou';以下の結果が返されます:
+---------+--------+-----+--------+--------------+------------------+------+ | user_id | name | age | gender | address | email | city | +---------+--------+-----+--------+--------------+------------------+------+ | 20 | Wang | 28 | M | Binjiang District, Hangzhou | a***@example.net | Hangzhou | +---------+--------+-----+--------+--------------+------------------+------+
サブフィールドを用いたトークン化テキスト照会の実行
トークン化テキストのサブフィールド機能は、LindormTable 2.8.0 以降および Elasticsearch と互換性のある LindormSearch を必要とします。該当バージョンを満たしていない場合は、「マイナーバージョンの更新」を行ってください。
背景情報
検索インデックスを作成する際、VARCHAR 型の列をトークン化タイプ(type=text)に設定すると、等価照会およびあいまい検索においてトークン化が適用されます。これにより、予期しない結果が生じる場合があります。
たとえば、address(type=text,analyzer=ik) 列を設定すると、インデックスを作成する際にシステムはトークナイザポリシーに基づいてテキストをトークンに分割します。たとえば、Binjiang District, Hangzhou は、Hangzhou および Binjiang District の 2 つのトークンになります。その結果、LIKE を使用するあいまい検索は、対象となる語が複数のトークンに分割されるため失敗する可能性があります。
以下の例では、District および Binjiang が別々のトークンに分割されるため、マッチしません。このクエリは結果を返しません。
SELECT * FROM search_table WHERE city LIKE '%Binjiang District%' LIMIT 10;有効化方法
VARCHAR 型の列がトークン化テキスト照会、あいまい検索、および等価照会を同時にサポートできるようにするには、トークン化テキストのサブフィールド機能を有効化します。
この機能を有効化するには、インデックス作成時に列属性を type=string,textSubField=true,analyzer=ik に設定します。ご使用のユースケースに応じて適切な analyzer を選択してください。詳細については、「アナライザの種類」をご参照ください。以下に例を示します。
CREATE INDEX idx USING SEARCH ON search_table(user_id,address(type=string, textSubField=true, analyzer=ik));既に検索インデックスが存在しており、トークン化テキストのサブフィールド機能を有効化したい場合は、「単一テーブルにおける複数検索インデックス(パブリックプレビュー)」を用いて、トークン化テキストのサブフィールドを含む新しい検索インデックスを作成し、その後クエリを新しいインデックスに切り替えることができます。
照会方法
デフォルトでは、等価照会およびあいまい検索は完全一致マッチを用います。トークン化テキスト照会は MATCH 関数を用います。以下に、3 つの代表的な照会方法とその結果を示します。
等価照会
例 1:
SELECT * FROM search_table WHERE address='Hangzhou' LIMIT 10;この照会は結果を返さないため、
address列に文字列Hangzhouと完全に一致するレコードが存在しません。例 2:
SELECT * FROM search_table WHERE address='Binjiang District, Hangzhou' LIMIT 10;以下の結果が返されます:
+---------+--------+-----+--------+--------------+------------------+------+ | user_id | name | age | gender | address | email | city | +---------+--------+-----+--------+--------------+------------------+------+ | 20 | Wang | 28 | M | Binjiang District, Hangzhou | a***@example.net | Hangzhou | +---------+--------+-----+--------+--------------+------------------+------+あいまい検索
例:
SELECT * FROM search_table WHERE address like '%Binjiang%' LIMIT 10;以下の結果が返されます:
+---------+--------+-----+--------+--------------+------------------+------+ | user_id | name | age | gender | address | email | city | +---------+--------+-----+--------+--------------+------------------+------+ | 20 | Wang | 28 | M | Binjiang District, Hangzhou | a***@example.net | Hangzhou | +---------+--------+-----+--------+--------------+------------------+------+トークン化テキスト照会
例:
SELECT * FROM search_table WHERE MATCH (address) AGAINST ('Hangzhou') LIMIT 10;以下の結果が返されます:
+---------+--------+-----+--------+--------------+------------------+------+ | user_id | name | age | gender | address | email | city | +---------+--------+-----+--------+--------------+------------------+------+ | 6 | Li | 32 | M | Yuhang District, Hangzhou | a***@example.net | Hangzhou | | 20 | Wang | 28 | M | Binjiang District, Hangzhou | a***@example.net | Hangzhou | +---------+--------+-----+--------+--------------+------------------+------+