當前位置:編程學習大全網 - 源碼下載 - Elasticsearch通關教程(五):如何通過SQL查詢Elasticsearch

Elasticsearch通關教程(五):如何通過SQL查詢Elasticsearch

前言

這篇博文本來是想放在全系列的大概第五、六篇的時候再講的,畢竟查詢是在索引創建、索引文檔數據生成和壹些基本概念介紹完之後才需要的。當前面的壹些知識概念全都講解完之後再講解查詢是最好的,但是最近公司項目忙經常加班,畢竟年底了。但是不寫的話我怕會越拖越久,最後會不了了之了,所以剛好上海周末下雪,天冷無法出門,就坐在電腦前敲下了這篇博文。因為公司的查詢這塊是我負責的所以我研究了比較多點,寫起來也順手些。那麽進入正文。

為什麽用SQL查詢

前面的文章介紹過,Elasticsearch 的官方查詢語言是 Query DSL,既然是官方指定的,說明最吻合 ES 的強大功能,為ES做支撐。那麽我們為什麽還用 SQL 查詢?這是否是多此壹舉了呢?

其實,存在畢竟有存在的道理,存在即合理。SQL 作為壹個數據庫查詢語言,它語法簡潔,書寫方便而且大部分服務端程序員都清楚了解和熟知它的寫法。但是作為壹個 ES 萌新來說,就算他已經是壹位編程界的老江湖,但是如果他不熟悉 ES ,那麽他如果要使用公司已經搭好的 ES 服務,他必須要先學習 Query DSL,學習成本也是壹項影響技術開發進度的因素而且不穩定性高。但是如果 ES 查詢支持 SQL的話,那麽也許就算他是工作壹兩年的同學,他雖然不懂 ES的復雜概念,他也能很好的使用 ES 而且順利的參加到開發的隊伍中,畢竟SQL 誰不會寫呢?

Elasticsearch-SQL

我們正式介紹下我們的主角 - Elasticsearch-SQL,Elasticsearch-SQL不屬於 Elasticsearch 官方的,它是 NLPChina(中國自然語言處理開源組織)開源的壹個 ES 插件,主要功能是通過 SQL 來查詢 ES,其實它的底層是通過解釋 SQL,將SQL 轉換為 DSL 語法,再通過DSL 查詢。

Elasticsearch-SQL目前已經支持大概所有版本的 ES,而且最近的6.5.x的也在支持的範圍了,所以可以看得出來維護的還是蠻頻繁的。

安裝插件

由於 ES 2.x 和 5.x 的版本區別(詳細參考:版本選擇),我們安裝 ES 插件是有點區別的,

在 5.0之前的安裝方式為:plugin install

./bin/plugin install </groupId>

<artifactId>elasticsearch-sql</artifactId>

<version>x.x.x.0</version>

</dependency>

版本號(x.x.x)需要和 Elasticsearch的版本對應上,具體的對應關系大致可以參考下圖:

但是不是所有的版本,我們都可以從Maven Repository裏獲取到,我們如果直接從Maven 倉庫裏面只能獲取如下幾個版本的依賴,其中缺少很多版本:

那如果我們使用的是其他版本的 ES 如何解決依賴 jar包問題呢?還記得我們開始下載插件解壓後的sql文件夾嗎?例如6.5.0版本的插件的解壓後文件夾內容如下:

這裏面就有我們需要的 jar包,有了 jar包就好辦了,我們可以直接加入到項目中,當然最好的方式是上傳到公司的私有倉庫裏面,然後通過pom文件依賴進來。

搭建項目

jar包問題解決之後就可以正式進入開發階段了,新建壹個springboot項目,引入各項依賴,壹切準備就尋後,如何連接ES呢?

這裏有兩種方式可以實現我們的功能,壹個是通過JDBC的方式,連接數據庫壹樣連接ES。還有壹種就是通過 tansport client 方式。

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();

}

這種方式是最直觀的,用到了Druid連接池,所以我們還需要在項目中引入druid依賴,而且需要註意依賴的版本,否則會報錯。

<dependency>

<groupId>com.alibaba</groupId>

<artifactId>druid</artifactId>

<version>1.0.15</version>

</dependency>

這種方式很好理解,而且開發也方便,但是我在項目中應用了發現它有很多不足,所以我最後還是自己看了下源碼,通過API的方式重新封裝調用。

API方式

其實 elasticsearch-sql 沒有提供開發的 文檔,並沒有介紹如何通過調用 Java API方式開發,我們需要閱讀 elasticsearch-sql 的源代碼來發現它的service,然後包裝成我們需要的,通過閱讀源碼我們發現了如下壹個功能明顯的Service類。

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 類中有壹個explain方法,接收的參數就是壹個字符串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 e

  • 上一篇:如何轉換FLV到iPad和iPad上播放FLV視頻
  • 下一篇:那些每天堅持早起的人都是這麽做到的?
  • copyright 2024編程學習大全網