ElasticSearchのクエリ:DSLの代わりにSQLを使用

ES7.xバージョンのx-packにはElasticSearch SQLが付属しており、SQL REST API、SQL CLIなどを介してSQLクエリを直接使用できます。

SQL REST API

Kibanaコンソールに入力します。

POST /_sql?format=txt
{
  "query": "SELECT * FROM library ORDER BY page_count DESC LIMIT 5"
}

上記のSQLを独自のSQLステートメントに置き換えます。戻り形式は次のとおりです。

    author      |        name        |  page_count   | release_date
-----------------+--------------------+---------------+------------------------
Peter F. Hamilton|Pandora's Star      |768            |2004-03-02T00:00:00.000Z
Vernor Vinge     |A Fire Upon the Deep|613            |1992-06-01T00:00:00.000Z
Frank Herbert    |Dune                |604            |1965-06-01T00:00:00.000Z

SQL CLI

elasticsearch-sql-cliは、ESのインストール時にbinディレクトリにあるスクリプトファイルです。または、個別にダウンロードすることもできます。ESディレクトリで実行します

./bin/elasticsearch-sql-cli https://some.server:9200

クエリするSQLを入力してください

sql> SELECT * FROM library WHERE page_count > 500 ORDER BY page_count DESC;
     author      |        name        |  page_count   | release_date
-----------------+--------------------+---------------+---------------
Peter F. Hamilton|Pandora's Star      |768            |1078185600000
Vernor Vinge     |A Fire Upon the Deep|613            |707356800000
Frank Herbert    |Dune                |604            |-144720000000

SQLからDSL

キバナを入力:

POST /_sql/translate
{
  "query": "SELECT * FROM library ORDER BY page_count DESC",
  "fetch_size": 10
}

変換されたDSLクエリを取得できます。

{
  "size": 10,
  "docvalue_fields": [
    {
      "field": "release_date",
      "format": "epoch_millis"
    }
  ],
  "_source": {
    "includes": [
      "author",
      "name",
      "page_count"
    ],
    "excludes": []
  },
  "sort": [
    {
      "page_count": {
        "order": "desc",
        "missing": "_first",
        "unmapped_type": "short"
      }
    }
  ]
}

クエリ関連のステートメントが生成されているため、DSLを快適に使用するには、これに基づいて適切に変更する必要があります。

ここでは、ES SQLでサポートされるSQLステートメントと、誤用を回避する方法について詳しく説明します

まず、ES SQLでサポートされているSQLステートメントのSQL用語とES用語の対応を理解する必要があります。

ES SQLの構文サポートは主にANSI SQL標準に準拠しており、サポートされているSQLステートメントにはDMLクエリと一部のDDLクエリが含まれます。
DDLクエリは、次のような:DESCRIBE tableSHOW COLUMNS IN tableやや無味、私たちは主を探しSELECT,FunctionDMLクエリをサポート。

選択する

文法構造は次のとおりです。

SELECT [TOP [ count ] ] select_expr [, ...]
[ FROM table_name ]
[ WHERE condition ]
[ GROUP BY grouping_element [, ...] ]
[ HAVING condition]
[ ORDER BY expression [ ASC | DESC ] [, ...] ]
[ LIMIT [ count ] ]
[ PIVOT ( aggregation_expr FOR column IN ( value [ [ AS ] alias ] [, ...] ) ) ]

0-Nテーブルから行データを取得することを表します。SQLの実行順序は次のとおりです。

  1. すべてFROMのキーワードを取得して、テーブル名を決定します。

  2. WHEREフィルターで除外する条件がある場合、すべてのラインが満たされません。

  3. GROUP BY条件がある場合はパケット集約、HAVING条件がある場合は重合結果がフィルタリングされます。

  4. 前の手順で取得した結果をselect_expr計算して、返された特定のデータを決定します。

  5. ORDER BY条件がある場合は、データの並べ替えを返しました。

  6. LIMITor TOP条件がある場合、前のステップの結果のサブセットが返されます。

一般的に使用されるSQLとは、ES SQLのサポートTOP [ count ]PIVOT ( aggregation_expr FOR column IN ( value [ [ AS ] alias ] [, ...] ) )句の2つの違いがあります
TOP [ count ]SELECT TOP 2 first_name FROM emp最大で2つのデータを返すことを意味する場合LIMIT条件共有することはできません
PIVOTこの句は、その後の操作のために、その集計条件によって取得された結果の行から列への変換を実行します。使ったことがないので紹介しません。

関数

上記のSQLに基づいて、フィルタリング、集約、ソート、およびページング用のSQLを実際に使用できます。ただし、全文検索、集約、およびグループ化機能を備えたリッチSQLを作成するには、ES SQLでのFUNCTIONサポートについてさらに学ぶ必要があります。サポートされている関数名とそのタイプ
をリストするために使用しSHOW FUNCTIONSます。

SHOW FUNCTIONS;

      name       |     type
-----------------+---------------
AVG              |AGGREGATE
COUNT            |AGGREGATE
FIRST            |AGGREGATE
FIRST_VALUE      |AGGREGATE
LAST             |AGGREGATE
LAST_VALUE       |AGGREGATE
MAX              |AGGREGATE
MIN              |AGGREGATE
SUM              |AGGREGATE
........

主に、集約、グループ化、および全文検索に関連する一般的な機能について説明します。

全文照合機能

MATCH:DSLのmatchおよびmulti_matchクエリに相当します。

MATCH(
    field_exp,       --字段名称
    constant_exp,       --字段的匹配值
    [, options])       --可选项

使用例:

SELECT author, name FROM library WHERE MATCH(author, 'frank');

    author     |       name
---------------+-------------------
Frank Herbert  |Dune
Frank Herbert  |Dune Messiah
SELECT author, name, SCORE() FROM library WHERE MATCH('author^2,name^5', 'frank dune');

    author     |       name        |    SCORE()
---------------+-------------------+---------------
Frank Herbert  |Dune               |11.443176
Frank Herbert  |Dune Messiah       |9.446629

QUERY:DSLのquery_stringに相当します。

QUERY(
    constant_exp      --匹配值表达式
    [, options])       --可选项

使用例:

SELECT author, name, page_count, SCORE() FROM library WHERE QUERY('_exists_:"author" AND page_count:>200 AND (name:/star.*/ OR name:duna~)');

      author      |       name        |  page_count   |    SCORE()
------------------+-------------------+---------------+---------------
Frank Herbert     |Dune               |604            |3.7164764
Frank Herbert     |Dune Messiah       |331            |3.4169943

SCORE():入力データと返されたデータの関連性を返します。
使用例:

SELECT SCORE(), * FROM library WHERE MATCH(name, 'dune') ORDER BY SCORE() DESC;

    SCORE()    |    author     |       name        |  page_count   |    release_date
---------------+---------------+-------------------+---------------+--------------------
2.2886353      |Frank Herbert  |Dune               |604            |1965-06-01T00:00:00Z
1.8893257      |Frank Herbert  |Dune Messiah       |331            |1969-10-15T00:00:00Z

集計関数

AVG(numeric_field) :数値フィールドの平均値を計算します。

SELECT AVG(salary) AS avg FROM emp;

COUNT(expression):COUNT()のfield_nameに対応するnull値のデータを含む、入力データの総数を返します。
COUNT(ALL field_name):入力データの総数を返します。field_nameに対応する、値がnullのデータは除きます。
COUNT(DISTINCT field_name):nullでない入力データのfield_nameに対応する値の総数を返します。
SUM(field_name):入力データの数値フィールドfield_nameに対応する値の合計を返します。
MIN(field_name):入力データの数値フィールドfield_nameに対応する値の最小値を返します。
MAX(field_name):入力データの数値フィールドfield_nameに対応する最大値を返します。

グループ化機能

ここでのグループ化機能は、DSLでのバケットのグループ化に対応しています。

HISTOGRAM:構文は次のとおりです。

HISTOGRAM(
           numeric_exp,    --数字表达式,通常是一个field_name
           numeric_interval    --数字的区间值
)

HISTOGRAM(
           date_exp,      --date/time表达式,通常是一个field_name
           date_time_interval      --date/time的区间值
)

以下は、毎年1月1日の早朝の出生のデータを返します。

ELECT HISTOGRAM(birth_date, INTERVAL 1 YEAR) AS h, COUNT(*) AS c FROM emp GROUP BY h;


           h            |       c
------------------------+---------------
null                    |10
1952-01-01T00:00:00.000Z|8
1953-01-01T00:00:00.000Z|11
1954-01-01T00:00:00.000Z|8
1955-01-01T00:00:00.000Z|4
1956-01-01T00:00:00.000Z|5
1957-01-01T00:00:00.000Z|4
1958-01-01T00:00:00.000Z|7
1959-01-01T00:00:00.000Z|9
1960-01-01T00:00:00.000Z|8
1961-01-01T00:00:00.000Z|8
1962-01-01T00:00:00.000Z|6
1963-01-01T00:00:00.000Z|7
1964-01-01T00:00:00.000Z|4
1965-01-01T00:00:00.000Z|1

ES SQLの制限

ES SQLとES DSLは完全に機能的に一致しているわけではないため、公式ドキュメントで言及されているSQLの制限は次のとおりです。

大きなクエリはParsingExceptionをスローする場合があります

解析フェーズでは、非常に大きなクエリがメモリを大量に消費するため、Elasticsearch SQLエンジンは解析を中止し、エラーをスローします。

ネストされた型フィールドの表現

SQLはネストされたタイプのフィールドをサポートせず、使用のみできます

[nested_field_name].[sub_field_name]

このフォームは、インラインサブフィールドを参照します。
使用例:

SELECT dep.dep_name.keyword FROM test_emp GROUP BY languages;

ネストされた型フィールドは、whereおよびorder byのスカラー関数では使用できません

彼らは、次のSQLの通りですエラー

SELECT * FROM test_emp WHERE LENGTH(dep.dep_name.keyword) > 5;

SELECT * FROM test_emp ORDER BY YEAR(dep.start_date);

複数のネストされたフィールドの同時クエリをサポートしていません

たとえば、ネストされたフィールドのnested_Aとnested_Bは同時に使用できません。

ネストされた内部フィールドのページング制限

ページングクエリにネストされたフィールドがある場合、ページングの結果は正しくない可能性があります。これは、ESのページネーションクエリがルートのネストされたドキュメントで発生し、その内部フィールドでは発生しないためです。

キーワードタイプのフィールドはノーマライザをサポートしていません

配列型フィールドをサポートしていません

これは、SQLのフィールドが1つの値にのみ対応しているためです。この場合、上記のSQL To DSL APIを使用してDSLステートメントに変換し、DSLを使用してクエリを実行できます。

集計ソートの制限

  • 並べ替えフィールドは集約バケット内のフィールドである必要があります。ESSQL CLIはこの制限を破りますが、上限は512行を超えることはできません。そうしないと、並べ替え段階で例外がスローされます。次のLimitような句を使用することをお勧めします

SELECT * FROM test GROUP BY age ORDER BY COUNT(*) LIMIT 100;
  • 集約ソートのソート条件は、スカラー関数または単純な演算子操作をサポートしていません。集計後の複雑なフィールド(たとえば、集計関数を含む)は、並べ替え条件では使用できません。

エラーの例を次に示します。

SELECT age, ROUND(AVG(salary)) AS avg FROM test GROUP BY age ORDER BY avg;

SELECT age, MAX(salary) - MIN(salary) AS diff FROM test GROUP BY age ORDER BY diff;

サブクエリの制限

サブクエリがこの構造を含んでいるGROUP BY or HAVINGか、SELECT X FROM (SELECT ...) WHERE [simple_condition]この構造よりも複雑である場合、失敗する可能性があります。

TIMEデータ型フィールドはGROUP BY条件とHISTOGRAM関数をサポートしていません

次のクエリなどは間違っています:

SELECT count(*) FROM test GROUP BY CAST(date_created AS TIME);

SELECT HISTOGRAM(CAST(birth_date AS TIME), INTERVAL '10' MINUTES) as h, COUNT(*) FROM t GROUP BY h

ただし、TIMEタイプのフィールドをスカラー関数としてラップして返すには、次のようにGROUP BYをサポートします。

SELECT count(*) FROM test GROUP BY MINUTE((CAST(date_created AS TIME));

返されるフィールドの制限
フィールドがソースに格納されていない場合は、クエリできません。keyword, date, scaled_float, geo_point, geo_shapeこれらのタイプのフィールドは_source、戻りからではなく、戻りからものであるため、このような制限からのものdocvalue_fieldsです。

方法はありませんが、テクニックは達成できます。方法がない場合は、テクニックで終わります

みんながJava Wayパブリックアカウントをフォローすることを歓迎します

良い記事、私は読んでいます❤️

おすすめ

転載: blog.csdn.net/hollis_chuang/article/details/108675333