どのようにSQLクエリElasticsearch

序文

このブログは、おそらく第五、6再訪時間のフルレンジを入れたかった、すべての後に、クエリがインデックス、ドキュメントのインデックスデータの生成に作成され、唯一のフィニッシュ後に導入し、いくつかの基本的な概念を必要としています。その後、現在のいくつかの知識は、すべてのクエリの完全な表面を説明する概念を説明した後に最高ですが、忙しい最近、同社のプロジェクトは、多くの場合、年度終了後、残業。しかし、私は、私は彼らだけ延長することを恐れて、書いていない、最終的に問題の残りの部分を聞かせて、これだけの上海の週末、雪、寒さは、コンピュータQiaoxiaこのブログの前に座って、出て行くことはできません。同社私はこの問い合わせを担当していたので私はより多くのポイントを学ぶだけでなく、より簡単に書くこと。次に、テキストを入力します。

SQLクエリを使用する理由

前の記事導入、Elasticsearch公式クエリ言語クエリDSL、それが正式に指定されているので、ESと一致最も強力な説明は、ESがサポートしています。では、なぜ我々はまだSQLクエリを使用していますか?これは不必要であるかどうか?

実際には、すべての後に、存在し、合理的な存在である、理由があります。SQLデータベースクエリ言語の構文はシンプルであるため、書きやすいとサーバ側のプログラマのほとんどは、それと文言の明確な理解に精通しています。しかし、新しいES孟として彼はすでにプログラミング業界の古い旅行者だったが、彼はESサービスに設定された会社を使用したい場合は、彼は最初のクエリDSLを学ばなければならないので、彼は、おなじみのESなかった場合は、学習しても誰が、コストは技術の発展と安定の進行に影響を与える要因は高くないにもあります。しかし、ES SQLクエリのサポートは、多分彼は一年や学生のうちの2つを働いていた場合でも、彼はES複合体の概念を理解していなかったならば、彼はESをうまく利用することに成功し、チームの開発に参加することができ、結局、SQL人それを書きますか?

Elasticsearch-SQL

私たちの主人公に当社の正式な導入 - Elasticsearch-SQL、Elasticsearch-SQLはElasticsearch公式に属していない、それはNLPChina(中国の自然言語処理、オープンソース)であるESプラグインを開いて、主な機能は、実際に、それはだ、SQL経由でESを照会することですこれは、基礎となるSQL、DSL構文にSQL変換した後、DSLクエリを通じてによって説明されます。

あなたはそのメンテナンスがまだかなり頻繁で見ることができますので、Elasticsearch-SQLは現在、ESについてのすべてのバージョンをサポートしており、最近の6.5.xの範囲もサポートされています。

プラグインをインストールします。

ES 2.xと5.xのバージョンの違いに起因し(詳細な参照:バージョンを選択し)、我々は、プラグ-ESは少し異なっているインストール

インストールの前に5.0は、以下のとおりです。plugin install

./bin/plugin install https://github.com/NLPchina/elasticsearch-sql/releases/download/2.4.6.0/elasticsearch-sql-2.4.6.0.zip
复制代码

5.0のインストール(の6.xを含む)の後:elasticsearch-plugin install

./bin/elasticsearch-plugin install https://github.com/NLPchina/elasticsearch-sql/releases/download/5.0.1/elasticsearch-sql-5.0.1.0.zip
复制代码

我々は正常にインストールされていない場合、我々は直接ダウンロードできるプラグインElasticsearch-SQLの圧縮パッケージ、そして抽出し、完了リネームフォルダの後sql、ES用のインストールパス入れpluginsたとえば、ディレクトリを:..\elasticsearch-6.4.0\plugins\sql

あなたがこれを実行したら、それ以外の場合はエラーになり、サーバーElasticsearchを再起動する必要がありますInvalid index name [sql], must not start with '']; ","status":400}

ビジュアルフロントエンドインタフェース

Elasticsearch-SQLプラグインは、次のようにインターフェースがあり、あなたはSQLクエリを実行することができ、視覚的なインターフェースを提供します。

elasticsearchの1.x / 2.xでは、次のアドレスに直接アクセスすることができます。

http://localhost:9200/_plugin/sql/
复制代码

インストールNode.jsのと必要とelasticsearchの5.x / 6.xでは、ではダウンロードをしてサイトを解凍した後、Webフロントは次のように終了し起動します。

cd site-server
npm install express --save
node node-server.js 
复制代码

クエリの構文

何の問題は、今、あなたはSQLクエリのESを使用することができ、そのうちのいくつかは、通常のSQL構文であり、いくつかは、SQL構文を超えて、同等のSQL構文の拡張されていない場合は上記の操作後、ESクエリの形式は次のとおりです。

http://localhost:9200/_sql?sql=select * from indexName limit 10
复制代码

単純な問合せ

単純なクエリ構文のファースト:

SELECT fields from indexName WHERE conditions
复制代码

あなたが見ることができ、私たちの前のクエリ、テーブル名tableNameの場所は現在のインデックスタイプがある場合、あなたも書くことができ、インデックスINDEXNAMEの名前を変更しました:

SELECT fields from indexName/type WHERE conditions
复制代码

次のようにも同時にインデックスの複数の種類を確認することができ、構文は次のとおりです。

SELECT fields from indexName/type1,indexName/type2 WHERE conditions
复制代码

あなたは、現在のSQLは、キーワードによってそうするSQLクエリDSL Elasticsearchとして解釈される方法を知りたい場合explain

http://localhost:9200/_sql/_explain?sql=select * from indexName limit 10
复制代码

クラス機能は、重合を問い合わせます

select COUNT(*),SUM(age),MIN(age) as m, MAX(age),AVG(age)
  FROM bank GROUP BY gender ORDER BY SUM(age), m DESC
复制代码

クエリへの追加機能強化

サーチ

 SELECT address FROM bank WHERE address = matchQuery('880 Holmes Lane') ORDER BY _score DESC LIMIT 3
复制代码

集計

  • 範囲の年齢層20-25,25-30,30-35,35-40
SELECT COUNT(age) FROM bank GROUP BY range(age, 20,25,30,35,40)
复制代码
  • 日によってレンジ日付グループ
SELECT online FROM online GROUP BY date_histogram(field='insert_time','interval'='1d')
复制代码
  • お使いの設定により、範囲の日付のグループ
  SELECT online FROM online GROUP BY date_range(field='insert_time','format'='yyyy-MM-dd' ,'2014-08-18','2014-08-17','now-8d','now-7d','now-6d','now')
复制代码

地理問い合わせ

Elasticsearchは一緒の場所、全文検索、構造検索および分析を組み合わせることができます。Elasticsearch-SQLは、基本的に、対応Elasticsearch章をすべてのロケーション関連のクエリをサポートしているジオロケーション

図1に示すように、カートリッジフィルタモデルの地理座標

地理座標カートリッジフィルタモデル(GEOバウンディングボックスフィルタ)、矩形の上、下、左と右の境界を指定するために、フィルタは、単に、経度は左右の境界との間の座標か否かを判断する緯度の上限と下限の間にあります。

構文:

GEO_BOUNDING_BOX(fieldName,topLeftLongitude,topLeftLatitude,bottomRightLongitude,bottomRightLatitude)
复制代码

例:

SELECT * FROM location WHERE GEO_BOUNDING_BOX(center,100.0,1.0,101,0.0)
复制代码

図2に示すように、フィルタの距離

距離フィルタ(geo_distance)を中心として所定の位置にそれらの地理的座標は文書の特定の距離内に入る見つけるために、円を描きます。

構文:

GEO_DISTANCE(fieldName,distance,fromLongitude,fromLatitude)
复制代码

例:

SELECT * FROM location WHERE GEO_DISTANCE(center,'1km',100.5,0.5)
复制代码

図3に示すように、フィルタの距離間隔

フィルタ距離範囲(レンジ距離フィルタ)を中心として所定の位置に、最小値と最大距離との間の所定の時点で、それぞれ二円所定の距離、及びポイントを識別するために指定された距離geo_distance filterだけ違いはそれがあるRange Distance filterリングである、それは内輪に落ちる文書の一部を除外します。

構文:

GEO_DISTANCE_RANGE(fieldName,distanceFrom,distanceTo,fromLongitude,fromLatitude)
复制代码

例:

SELECT * FROM location WHERE GEO_DISTANCE_RANGE(center,'1m','1km',100.5,0.50001)
复制代码

図4に示すように、ポリゴンフィルタ(点に作品)

ポリゴンを落下ポイントを探します。このフィルタは、高い価格を使用しています。あなたがそれを使用する必要があると感じたとき、それが見することが最善であるGEO-形状

構文:

GEO_POLYGON(fieldName,lon1,lat1,lon2,lat2,lon3,lat3,...)
复制代码

例:

SELECT * FROM location WHERE GEO_POLYGON(center,100,0,100.5,2,101.0,0)
复制代码

5、GeoShapeと交差するフィルタ(geoshapesの作品)

あなたは使うべきWKTのクエリの形状表現を。構文:

GEO_INTERSECTS(fieldName,'WKT')
复制代码

例:

SELECT * FROM location WHERE GEO_INTERSECTS(place,'POLYGON ((102 2, 103 2, 103 3, 102 3, 102 2))
复制代码

地理の詳細クエリが参照できるため、ここで

実際の使用状況

私たちは、このシリーズでは、最初のチュートリアル当ウェブサイトのインデックスでは、作成しnba、以下のように、例を作るために:

** 1 **問い合わせNBAのすべてのチーム情報

http://localhost:9200/_sql?sql=select * from nba limit 10
复制代码

クエリ結果:

** 2 **問い合わせチーム率いるスタージェームズ情報

http://localhost:9200/_sql?sql=select * from nba where topStar  = "勒布朗·詹姆斯"
复制代码

クエリ結果:

** 3 **降順に設立よります

http://localhost:9200/_sql?sql=select * from nba order by date desc
复制代码

クエリ結果:

4 ** **問合せは、以上の5つの優勝チームの情報を持っています

http://localhost:9200/_sql?sql=select * from nba where championship  >= 5
复制代码

クエリ結果:

それぞれ1-5,5-10,10-15,15-20間* 5、クエリの数は、**優勝チーム番号の範囲

http://localhost:9200/_sql?sql=SELECT COUNT(championship) FROM nba GROUP BY range(championship, 1,5,10,15,20) 
复制代码

クエリ結果:

もちろん、ここでの特定の実装の文言に複数存在アピールしないようにされており、関心のある読者は、ここで見つけることができ、独自のプロジェクトをビルドして、次の、より多くの機能のSQL文言を試すことができます。

Java実装

すでにインストールとElasticsearch-SQLの使用が記載されている通り、その後、どのように我々はプロジェクトでそれを使用するのです、Elasticsearch-SQLには、結果を照会するために、DSLに変換され、SQL言語を解析して開発した基盤となるJava言語で、キーへの解析結果 - 値の固定フォーマットが返されます。

依存性の導入

使用前に、我々は導入達人に依存する必要があります

<dependency>
    <groupId>org.nlpcn</groupId>
    <artifactId>elasticsearch-sql</artifactId>
    <version>x.x.x.0</version>
</dependency>
复制代码

バージョン番号(XXX)と実質的に図17に示されている間Elasticsearch、特定の対応を必要と対応バージョン:

しかし、すべてのバージョンは、私たちができるからではないのMavenリポジトリ我々は唯一のように複数のバージョンを取得することができれば、多くのバージョンが欠けているのMavenリポジトリから直接依存し、に取得します:

私たちはES-に依存するJARパッケージの問題を解決する方法の異なるバージョンを使用している場合は?私たちはプラグインの抽出ダウンロードを開始した後に覚えているsql文件夹それを?たとえば、次のようにプラグインフォルダの内容のファイル6.5.0バージョンを解凍します。

我々はもちろん、最良の方法は、企業のプライベートリポジトリにアップロードされ、プロジェクトに直接加え、その後、POMファイルを介して来ることを頼りにしてもよいし、処理するためのjarパッケージに簡単で、瓶のパッケージを必要があります。

建築プロジェクト

問題を解決することができたjarパッケージした後、正式にどのようにそれを接続するために、ESを開発段階に入って、新しいspringbootプロジェクト、依存の導入を作成し、あなたはすべての準備ができていますか?

それは、接続ESとしてデータベースに接続する方法であるJDBC経由で当社の機能を実現するには、2つの方法があります。もう一つの方法は、tansportクライアントを介してです。

JDBCの道

サンプルコード

public void testJDBC() throws Exception {
        Properties properties = new Properties();
        properties.put("url", "jdbc:elasticsearch://192.168.3.31:9300,192.168.3.32:9300/" + TestsConstants.TEST_INDEX);
        DruidDataSource dds = (DruidDataSource) ElasticSearchDruidDataSourceFactory.createDataSource(properties);
        Connection connection = dds.getConnection();
        PreparedStatement ps = connection.prepareStatement("SELECT  gender,lastname,age from  " + TestsConstants.TEST_INDEX + " where lastname='Heath'");
        ResultSet resultSet = ps.executeQuery();
        List<String> result = new ArrayList<String>();
        while (resultSet.next()) {
              System.out.println(resultSet.getString("lastname") + "," + resultSet.getInt("age") + "," + resultSet.getString("gender"))
        }
        ps.close();
        connection.close();
        dds.close();
    }
复制代码

このアプローチは、最も直感的で、ドルイドは、接続プールを使用するため、我々はまた、ドルイドを導入する必要があるプロジェクトに依存している、だけでなく、依存バージョンを指摘し、それ以外の場合はエラーになります。

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.0.15</version>
</dependency>
复制代码

この方法では、十分に理解するだけでなく、開発するのは簡単ですが、私はそれは多くの欠点を持っているプロジェクトでアプリケーションを見つけたので、私は最終的にAPI呼び出しを再パッケージを経由して、自分自身のソースコードを見ました。

APIの方法

事実elasticsearch-SQLは、ドキュメントの開発を提供していませんでした、そして開発するためのJava APIの道を呼び出す方法を説明していないで、私たちはそのサービスを発見するelasticsearch-SQLのソースコードを読む必要がある、と我々は必要なものにパッケージ化、ソースコードを読み取ることによって、私たちは次のことを見つけますサービスクラスの大きな特徴。

public class SearchDao {

	private static final Set<String> END_TABLE_MAP = new HashSet<>();

	static {
		END_TABLE_MAP.add("limit");
		END_TABLE_MAP.add("order");
		END_TABLE_MAP.add("where");
		END_TABLE_MAP.add("group");

	}

	private Client client = null;


	public SearchDao(Client client) {
		this.client = client;
	}

    public Client getClient() {
        return client;
    }

    /**
	 * Prepare action And transform sql
	 * into ES ActionRequest
	 * @param sql SQL query to execute.
	 * @return ES request
	 * @throws SqlParseException
	 */
	public QueryAction explain(String sql) throws SqlParseException, SQLFeatureNotSupportedException {
		return ESActionFactory.create(client, sql);
	}
}
复制代码

クラスはメソッドを持って説明SearchDao、受信したパラメータは、文字列のSQLはQueryActionは以下のサブクラスを持つ抽象クラスであり、結果はQueryActionで、あります

図から分かるように、それぞれのサブクラスに対応する問合せの機能、集計クエリ、デフォルトのクエリ、削除、ハッシュクエリに参加する場合、クエリは、ネストされたクエリのように、接続されています。

QueryAction我々は方法QueryActionElasticExecutor executeAnyActionクラス、および内部処理によって得られた受け入れることができ、その後、対応する実行結果を得ることができます。

 public static Object executeAnyAction(Client client , QueryAction queryAction) throws SqlParseException, IOException {
        if(queryAction instanceof DefaultQueryAction)
            return executeSearchAction((DefaultQueryAction) queryAction);
        if(queryAction instanceof AggregationQueryAction)
            return executeAggregationAction((AggregationQueryAction) queryAction);
        if(queryAction instanceof ESJoinQueryAction)
            return executeJoinSearchAction(client, (ESJoinQueryAction) queryAction);
        if(queryAction instanceof MultiQueryAction)
            return executeMultiQueryAction(client, (MultiQueryAction) queryAction);
        if(queryAction instanceof DeleteQueryAction )
            return executeDeleteAction((DeleteQueryAction) queryAction);
        return null;
    }
复制代码

結果が得られ、それはオブジェクトタイプですが、我々はまた、カスタマイズされた外観を必要とするクラスに気づいた:ObjectResultsExtractorそのコンストラクタを次のように、3つのコンストラクタBooleanパラメータが含まれています。彼らの役割は、結果セットにあるIDを含めるために、我々がfalseに設定されているかどうか、タイプを含めるかどうか、スコアが含まれています。

public ObjectResultsExtractor(boolean includeScore, boolean includeType, boolean includeId) {
    this.includeScore = includeScore;
    this.includeType = includeType;
    this.includeId = includeId;
    this.currentLineIndex = 0;
}
复制代码

ObjectResultsExtractorそれはpulic外部を修正するための唯一の方法ですextractResults

public ObjectResult extractResults(Object queryResult, boolean flat) throws ObjectResultsExtractException {
    if (queryResult instanceof SearchHits) {
        SearchHit[] hits = ((SearchHits) queryResult).getHits();
        List<Map<String, Object>> docsAsMap = new ArrayList<>();
        List<String> headers = createHeadersAndFillDocsMap(flat, hits, docsAsMap);
        List<List<Object>> lines = createLinesFromDocs(flat, docsAsMap, headers);
        return new ObjectResult(headers, lines);
    }
    if (queryResult instanceof Aggregations) {
        List<String> headers = new ArrayList<>();
        List<List<Object>> lines = new ArrayList<>();
        lines.add(new ArrayList<Object>());
        handleAggregations((Aggregations) queryResult, headers, lines);
        
        // remove empty line。
        if(lines.get(0).size() == 0) {
            lines.remove(0);
        }
        //todo: need to handle more options for aggregations:
        //Aggregations that inhrit from base
        //ScriptedMetric

        return new ObjectResult(headers, lines);

    }
    return null;
}
复制代码

この時点で、私たちはそのクエリAPIの一般的な理解を持っている、と我々は単にGoogleの検索機能を完了することができ、私たちのプロジェクトに呼び出すために、次のコードを実行する必要があり、かつで終わるObjectResult最終的なクエリ結果が設定されています。

//1.解释SQL
SearchDao searchDao = new SearchDao(transportClient);
QueryAction queryAction = searchDao.explain(sql);
//2.执行        
Object execution = QueryActionElasticExecutor.executeAnyAction(searchDao.getClient(), queryAction);
//3.格式化查询结果            
ObjectResult result = (new ObjectResultsExtractor(true, false, false)).extractResults(execution, true);
复制代码

このように、コード開発が完了し、の実行結果をテストしましょう、私たち外国人は、3つのインターフェースを提供していますが、APIを照会するための方法である、JDBCは、問い合わせの方法と同様に、説明のSQLです。

@RestController
@RequestMapping("/es/data")
public class ElasticSearchController {

    @Autowired
    private ElasticSearchSqlService elasticSearchSqlService;

    @PostMapping(value = "/search")
    public CommonResult search(@RequestBody QueryDto queryDto) {
        SearchResultDTO resultDTO = elasticSearchSqlService.search(queryDto.getSql());
        return CommonResult.success(resultDTO.getResult());
    }

    @PostMapping(value = "/query")
    public CommonResult query(@RequestBody QueryDto queryDto) {
        SearchResultDTO resultDTO = elasticSearchSqlService.query(queryDto.getSql(), queryDto.getIndex());
        return CommonResult.success(resultDTO.getResult());
    }

    @PostMapping(value = "/explain")
    public CommonResult explain(@RequestBody QueryDto queryDto) {
        return CommonResult.success(elasticSearchSqlService.explain(queryDto.getSql()));
    }

}
复制代码

例要求:

例の結果:

概要

正式ES SQLクエリ言語をお勧めしますが、彼のために便利ではないが、ESの関係者はまた、これを実現するために開始します。6.3.0後のESのバージョンもSQLをサポートするために始めたが、彼は我々が道を通じてRESTを使用することができれば、X-パック方法を導入することであるが、私たちが開発に導入されているが、まだ少し問題であり、ジョブのプラチナ会員に必要、私は知りません未来は進むことはできません。

また、より便利が、SQLを使用するが、すべての後に、公式ではない、機能に欠陥が、そこにはDSLの強力な機能ではありません、そしてピット内よりますが、基本的なクエリをサポートすることを避けられません。それが強制されていない場合、私はまだDSLの使用をお勧めします、といくつかの簡単な操作を支援するためにSQLを使用することができます興味のある読者は私に集中できるのであれば、この記事のソースは、私のGithubにアップロードされているのGithub


個人公開番号:JaJian

JaJian:世間の注目数を引く長押しへようこそ!

分散型の説明と分析は、定期的にあなたのためのマイクロ層のインターネット企業やその他のサービス関連技術を提供します。




ます。https://juejin.im/post/5cf229d86fb9a07ee27afd65で再現

おすすめ

転載: blog.csdn.net/weixin_33674437/article/details/91428952