Elasticsearch SQL ORM查詢案例介紹

bboss ES SQL是針對es jdbc的替代解決方案

the best elasticsearch highlevel java rest api-----bboss     java

bboss 提供一組sql和fetchQuery API,可替代官方es jdbc模塊;採用bboss便可擁有bboss的客戶端自動發現和容災能力、對es、jdk、spring boot的兼容性能力,又能夠擁有es jdbc的全部功能,同時還解決了由於引入es jdbc致使項目對es版本的強依賴和兼容性問題,參考demo:git

orm查詢
https://gitee.com/bboss/eshelloword-booter/blob/master/src/test/java/org/bboss/elasticsearchtest/sql/SQLOrmTest.javagithub

分頁查詢
https://gitee.com/bboss/eshelloword-booter/blob/master/src/test/java/org/bboss/elasticsearchtest/sql/SQLPagineTest.javaspring

目前官方es sql提供的功能有限,也能夠在bboss中使用Elasticsearch-sql插件提供的功能,下面有專門的章節介紹。sql

本文詳細說明上面的案例:shell

1 orm查詢

1.1 定義orm查詢的實體bean

package org.bboss.elasticsearchtest.sql;

import com.frameworkset.orm.annotation.Column;

import java.util.Date;

public class DocObject {
	private int isnew;
	private Date createtime;
	private String content;
	private int documentId;
	private int channelId;

	/**
	 * 經過column指定索引文檔和對象屬性的映射關係
	 * 經過column註解還能夠指定日期格式和時區信息
	 * @Column(name="docInfo.author",dataformat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",timezone = "Etc/UTC",locale = "zh")
	 *
	 */
	@Column(name="docInfo.author")
	private String docInfoAuthor;

	public int getIsnew() {
		return isnew;
	}

	public void setIsnew(int isnew) {
		this.isnew = isnew;
	}

	public Date getCreatetime() {
		return createtime;
	}

	public void setCreatetime(Date createtime) {
		this.createtime = createtime;
	}

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}

	public int getDocumentId() {
		return documentId;
	}

	public void setDocumentId(int documentId) {
		this.documentId = documentId;
	}

	public int getChannelId() {
		return channelId;
	}

	public void setChannelId(int channelId) {
		this.channelId = channelId;
	}

	public String getDocInfoAuthor() {
		return docInfoAuthor;
	}

	public void setDocInfoAuthor(String docInfoAuthor) {
		this.docInfoAuthor = docInfoAuthor;
	}
}

實體定義說明:json

經過column指定索引文檔和對象屬性的映射關係,指定日期格式和時區信息,示例以下:api

@Column(name="docInfo.author")
private String docInfoAuthor;

指定屬性的映射關係、日期格式和時區信息,示例以下:    app

 @Column(name="docInfo.author",dataformat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",timezone = "Etc/UTC",locale = "zh")elasticsearch

執行orm查詢

以rest sql api爲例來介紹es 6.3.0的sql orm查詢功能

package org.bboss.elasticsearchtest.sql;

import org.frameworkset.elasticsearch.ElasticSearchHelper;
import org.frameworkset.elasticsearch.client.ClientInterface;
import org.frameworkset.elasticsearch.entity.sql.SQLRestResponse;
import org.frameworkset.elasticsearch.entity.sql.SQLRestResponseHandler;
import org.junit.Test;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 以rest sql api爲例來介紹es 6.3.0的sql orm查詢功能
 */
public class SQLOrmTest {

	/**
	 * 代碼中的sql檢索,返回Map類型集合,亦能夠返回自定義的對象集合
	 */
	@Test
	public void testDemoQuery(){
		ClientInterface clientUtil = ElasticSearchHelper.getRestClientUtil();
		List<Map> json = clientUtil.sql(Map.class,"{\"query\": \"SELECT * FROM demo\"}");


		System.out.println(json);
	}

	/**
	 * 代碼中的sql檢索,返回Map類型集合,亦能夠返回自定義的對象集合
	 */
	@Test
	public void testMapQuery(){
		ClientInterface clientUtil = ElasticSearchHelper.getRestClientUtil();
		List<Map> json = clientUtil.sql(Map.class,"{\"query\": \"SELECT * FROM dbclobdemo\"}");


		System.out.println(json);
	}
	/**
	 * 配置文件中的sql dsl檢索,返回Map類型集合,亦能夠返回自定義的對象集合
	 */
	@Test
	public void testMapSQLQueryFromDSL(){
		ClientInterface clientUtil = ElasticSearchHelper.getConfigRestClientUtil("esmapper/sql.xml");//初始化一個加載sql配置文件的es客戶端接口
		//設置sql查詢的參數
		Map params = new HashMap();
		params.put("channelId",1);
		List<Map> json = clientUtil.sql(Map.class,"sqlQuery",params);
		System.out.println(json);

	}

	/**
	 * 代碼中的sql檢索,返回Map類型對象,亦能夠返回自定義的對象
	 */
	@Test
	public void testMapObjectQuery(){
		ClientInterface clientUtil = ElasticSearchHelper.getRestClientUtil();
		Map json = clientUtil.sqlObject(Map.class,"{\"query\": \"SELECT * FROM dbclobdemo\"}");


		System.out.println(json);
	}
	/**
	 * 配置文件中的sql dsl檢索,返回Map類型對象,亦能夠返回自定義的對象
	 */
	@Test
	public void testMapObjectSQLQueryFromDSL(){
		ClientInterface clientUtil = ElasticSearchHelper.getConfigRestClientUtil("esmapper/sql.xml");//初始化一個加載sql配置文件的es客戶端接口
		//設置sql查詢的參數
		Map params = new HashMap();
		params.put("channelId",1);
		Map json = clientUtil.sqlObject(Map.class,"sqlQuery",params);
		System.out.println(json);

	}


	/**
	 * 代碼中的sql檢索,返回DocObject 類型集合
	 */
	@Test
	public void testObjectListQuery(){
		ClientInterface clientUtil = ElasticSearchHelper.getRestClientUtil();
		List<DocObject> json = clientUtil.sql(DocObject.class,"{\"query\": \"SELECT * FROM dbclobdemo\"}");


		System.out.println(json);
	}
	/**
	 * 配置文件中的sql dsl檢索,返回DocObject 類型集合
	 */
	@Test
	public void testObjectSQLQueryFromDSL(){
		ClientInterface clientUtil = ElasticSearchHelper.getConfigRestClientUtil("esmapper/sql.xml");//初始化一個加載sql配置文件的es客戶端接口
		//設置sql查詢的參數
		Map params = new HashMap();
		params.put("channelId",1);
		List<DocObject> json = clientUtil.sql(DocObject.class,"sqlQuery",params);
		System.out.println(json);

	}

	/**
	 * 代碼中的sql檢索,返回DocObject 類型對象
	 */
	@Test
	public void testObjectQuery(){
		ClientInterface clientUtil = ElasticSearchHelper.getRestClientUtil();
		DocObject json = clientUtil.sqlObject(DocObject.class,"{\"query\": \"SELECT * FROM dbclobdemo where documentId = 1\"}");
		System.out.println(json);
	}
	/**
	 * 配置文件中的sql dsl檢索,返回DocObject 類型對象
	 */
	@Test
	public void testConditionObjectSQLQueryFromDSL(){
		ClientInterface clientUtil = ElasticSearchHelper.getConfigRestClientUtil("esmapper/sql.xml");//初始化一個加載sql配置文件的es客戶端接口
		//設置sql查詢的參數
		Map params = new HashMap();
		params.put("channelId",1);
		DocObject json = clientUtil.sqlObject(DocObject.class,"sqlQuery",params);
		System.out.println(json);

	}
	/**
	 * sql轉換爲dsl
	 */
	@Test
	public void testTranslate(){
		ClientInterface clientUtil = ElasticSearchHelper.getRestClientUtil();
		String json = clientUtil.executeHttp("/_xpack/sql/translate",
				"{\"query\": \"SELECT * FROM dbclobdemo limit 5\",\"fetch_size\": 5}",
				ClientInterface.HTTP_POST
		);
		System.out.println(json);

	}

	/**
	 * 低階的檢索方法
	 */
	@Test
	public void testSQLRestResponse(){
		ClientInterface clientUtil = ElasticSearchHelper.getRestClientUtil();
		SQLRestResponse sqlRestResponse = clientUtil.executeHttp("/_xpack/sql",
																	"{\"query\": \"SELECT * FROM dbclobdemo where documentId = 1\"}",
																	ClientInterface.HTTP_POST,
																		new SQLRestResponseHandler());
		System.out.println(sqlRestResponse);
	}


}

每一個orm查詢方法的都有對應的功能註釋說明,能夠根據須要使用相關的方法。

代碼中用到的sql dsl腳本配置文件及內容:esmapper/sql.xml

<properties>
    <!--
        sql query

    -->
    <property name="sqlQuery">
        <![CDATA[
         {"query": "SELECT * FROM dbclobdemo where channelId=#[channelId]"}
        ]]>
    </property>


    <property name="sqlQueryWithStringParam">
        <![CDATA[
         {"query": "SELECT * FROM dbclobdemo where channelId=#[channelId] and docTitle='#[channelId,quoted=false]'"} ## sql中特定的字符串參數語法
        ]]>
    </property>
    <!--
        分頁sql query
        每頁顯示 fetch_size對應的記錄條數

    -->
    <property name="sqlPagineQuery">
        <![CDATA[
         {
         ## 指示sql語句中的回車換行符會被替換掉開始符,注意dsl註釋不能放到sql語句中,不然會有問題,由於sql中的回車換行符會被去掉,致使回車換行符後面的語句變道與註釋一行
         ##  致使dsl模板解析的時候部分sql段會被去掉
            "query": #"""
                    SELECT * FROM dbclobdemo



                        where channelId=#[channelId]
             """,
             ## 指示sql語句中的回車換行符會被替換掉結束符
            "fetch_size": #[fetchSize]
         }
        ]]>
    </property>

</properties>

咱們將配置文件放到工程resources目錄下面便可。sql配置說明:

sql中特定的字符串參數語法

{"query": "SELECT * FROM dbclobdemo where channelId=#[channelId] and docTitle='#[channelId,quoted=false]'"}

咱們使用#[xxx]類型變量傳遞sql參數時,若是是字符串內容會自動在值的兩邊帶上雙引號,可是在sql語句是字符串值是用單引號'來標識的,因此經過qutoed=false來指示解析引擎不要在值的兩邊加雙引號,而後在外部手動添加單引號:

'#[channelId,quoted=false]'

若是sql語句比較長,可能要換行,es暫時不支持多行sql語句的執行,bboss經過下面特定的語法,來包圍多行sql,sql解析引擎在第一次解析sql的時候講其中的多行sql解析爲一行:

#"""

...

...

"""

例如:

{
## 指示sql語句中的回車換行符會被替換掉開始符,注意dsl註釋不能放到sql語句中,不然會有問題,由於sql中的回車換行符會被去掉,致使回車換行符後面的語句變道與註釋一行
##  致使dsl模板解析的時候部分sql段會被去掉
   "query": #"""
           SELECT * FROM dbclobdemo



               where channelId=#[channelId]
    """,
    ## 指示sql語句中的回車換行符會被替換掉結束符
   "fetch_size": #[fetchSize]
}

經過fetch_size實現分頁查詢

package org.bboss.elasticsearchtest.sql;

import org.frameworkset.elasticsearch.ElasticSearchHelper;
import org.frameworkset.elasticsearch.client.ClientInterface;
import org.frameworkset.elasticsearch.entity.sql.SQLResult;
import org.junit.Test;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class SQLPagineTest {
	/**
	 * 代碼中的sql檢索,返回Map類型集合,亦能夠返回自定義的對象集合
	 */
	@Test
	public void testMapQuery(){
		ClientInterface clientUtil = ElasticSearchHelper.getRestClientUtil();
		SQLResult<Map> sqlResult = clientUtil.fetchQuery(Map.class,"{\"query\": \"SELECT * FROM dbclobdemo\",\"fetch_size\": 1}");

		do{
			List<Map> datas = sqlResult.getDatas();
			if(datas == null || datas.size() == 0){
				break;
			}
			else{
				System.out.println(datas.size());//處理數據
				sqlResult = sqlResult.nextPage();//獲取下一頁數據

			}

		}while(true);



	}
	/**
	 * 配置文件中的sql dsl檢索,返回Map類型集合,亦能夠返回自定義的對象集合
	 */
	@Test
	public void testMapSQLQueryFromDSL(){
		ClientInterface clientUtil = ElasticSearchHelper.getConfigRestClientUtil("esmapper/sql.xml");//初始化一個加載sql配置文件的es客戶端接口
		//設置sql查詢的參數
		Map params = new HashMap();
		params.put("channelId",1);
		params.put("fetchSize",1);
		SQLResult<Map> sqlResult = clientUtil.fetchQuery(Map.class,"sqlPagineQuery",params);

		do{
			List<Map> datas = sqlResult.getDatas();
			if(datas == null || datas.size() == 0){
				break;
			}
			else{
				System.out.println(datas.size());//處理數據
				sqlResult = sqlResult.nextPage();//獲取下一頁數據

			}

		}while(true);

	}




	/**
	 * 代碼中的sql檢索,返回DocObject 類型集合 
	 */
	@Test
	public void testObjectListQuery(){
		ClientInterface clientUtil = ElasticSearchHelper.getRestClientUtil();

		SQLResult<DocObject> sqlResult = clientUtil.fetchQuery(DocObject.class,"{\"query\": \"SELECT * FROM dbclobdemo\",\"fetch_size\": 1}");

		do{
			List<DocObject> datas = sqlResult.getDatas();
			if(datas == null || datas.size() == 0){
				break;
			}
			else{
				System.out.println(datas.size());//處理數據
				sqlResult = sqlResult.nextPage();//獲取下一頁數據

			}

		}while(true);


	}


	/**
	 * 配置文件中的sql dsl檢索,返回DocObject 類型集合 
	 */
	@Test
	public void testObjectSQLQueryFromDSL(){
		ClientInterface clientUtil = ElasticSearchHelper.getConfigRestClientUtil("esmapper/sql.xml");//初始化一個加載sql配置文件的es客戶端接口
		//設置sql查詢的參數

		Map params = new HashMap();
		params.put("channelId",1);
		params.put("fetchSize",1);
		SQLResult<DocObject> sqlResult = clientUtil.fetchQuery(DocObject.class,"sqlPagineQuery",params);

		do{
			List<DocObject> datas = sqlResult.getDatas();
			if(datas == null || datas.size() == 0){
				System.out.println(0);//處理數據
				break;
			}
			else{
				System.out.println(datas.size());//處理數據
				sqlResult = sqlResult.nextPage();//獲取下一頁數據

			}

		}while(true);

	}

	/**
	 * 配置文件中的sql dsl檢索,返回DocObject 類型集合 
	 */
	@Test
	public void testObjectSQLQueryFromDSL1(){
		ClientInterface clientUtil = ElasticSearchHelper.getConfigRestClientUtil("esmapper/sql.xml");//初始化一個加載sql配置文件的es客戶端接口
		//設置sql查詢的參數

		Map params = new HashMap();
		params.put("channelId",1);
		params.put("fetchSize",1);
		SQLResult<DocObject> sqlResult = clientUtil.fetchQuery(DocObject.class,"sqlPagineQuery",params);

		do{
			List<DocObject> datas = sqlResult.getDatas();
			if(datas == null || datas.size() == 0){
				System.out.println(0);//處理數據
				break;
			}
			else{
				System.out.println(datas.size());//處理數據
				sqlResult = clientUtil.fetchQueryByCursor(DocObject.class,sqlResult);//獲取下一頁數據,經過api獲取下一頁數據

			}

		}while(true);

	}

	/**
	 * 配置文件中的sql dsl檢索,返回DocObject 類型集合 
	 * 測試沒有返回數據的狀況
	 */
	@Test
	public void testNodataSQLQueryFromDSL1(){
		ClientInterface clientUtil = ElasticSearchHelper.getConfigRestClientUtil("esmapper/sql.xml");//初始化一個加載sql配置文件的es客戶端接口
		//設置sql查詢的參數

		Map params = new HashMap();
		params.put("channelId",2);
		params.put("fetchSize",1);
		SQLResult<DocObject> sqlResult = clientUtil.fetchQuery(DocObject.class,"sqlPagineQuery",params);


		do{
			List<DocObject> datas = sqlResult.getDatas();
			if(datas == null || datas.size() == 0){
				System.out.println(0);//處理數據
				break;
			}
			else{
				System.out.println(datas.size());//處理數據
				sqlResult = clientUtil.fetchQueryByCursor(DocObject.class,sqlResult);//獲取下一頁數據,經過api獲取下一頁數據

			}

		}while(true);

	}

	/**
	 * 配置文件中的sql dsl檢索,返回DocObject 類型集合 
	 */
	@Test
	public void testObjectSQLQueryFromDSL2(){
		ClientInterface clientUtil = ElasticSearchHelper.getConfigRestClientUtil("esmapper/sql.xml");//初始化一個加載sql配置文件的es客戶端接口
		//設置sql查詢的參數

		Map params = new HashMap();
		params.put("channelId",1);
		params.put("fetchSize",1);
		SQLResult<DocObject> sqlResult = clientUtil.fetchQuery(DocObject.class,"sqlPagineQuery",params);

		do{
			List<DocObject> datas = sqlResult.getDatas();
			if(datas == null || datas.size() == 0){
				System.out.println(0);//處理數據
				break;
			}
			else{
				System.out.println(datas.size());//處理數據
				sqlResult = clientUtil.fetchQueryByCursor(DocObject.class,sqlResult.getCursor(),sqlResult.getColumns());//獲取下一頁數據,經過api獲取下一頁數據

			}

		}while(true);

	}

	/**
	 * 代碼中的sql檢索,返回 DocObject類型集合
	 */
	@Test
	public void testCloseCursor(){
		ClientInterface clientUtil = ElasticSearchHelper.getRestClientUtil();

		SQLResult<DocObject> sqlResult = clientUtil.fetchQuery(DocObject.class,"{\"query\": \"SELECT * FROM dbclobdemo\",\"fetch_size\": 1}");
		List<DocObject> datas = sqlResult.getDatas();
		System.out.println(datas.size());//處理數據
		System.out.println(sqlResult.closeCursor());//只處理第一頁數據,就主動關閉分頁遊標
	}

	/**
	 * 代碼中的sql檢索,返回DocObject類型集合
	 */
	@Test
	public void testCloseCursor1(){
		ClientInterface clientUtil = ElasticSearchHelper.getRestClientUtil();

		SQLResult<DocObject> sqlResult = clientUtil.fetchQuery(DocObject.class,"{\"query\": \"SELECT * FROM dbclobdemo\",\"fetch_size\": 1}");
		List<DocObject> datas = sqlResult.getDatas();
		System.out.println(datas.size());//處理數據
		String ret = clientUtil.closeSQLCursor(sqlResult.getCursor());
		System.out.println(ret);//只處理第一頁數據,就主動關閉分頁遊標

	}
}

Elasticsearch-sql查詢

基於第三方Elasticsearch-sql插件的查詢功能的使用方法和bboss提供的查詢api使用方法一致,只是檢索的rest服務換成/_sql服務便可:

/**
	 * Elasticsearch-SQL插件功能測試方法
	 */
	public void testESSQL(){
		ClientInterface clientUtil = ElasticSearchHelper.getRestClientUtil();
		ESDatas<Map> esDatas =  //ESDatas包含當前檢索的記錄集合,最多10條記錄,由sql中的limit屬性指定
				clientUtil.searchList("/_sql",//sql請求
						"select * from vem_order_index_2018 limit 0,10", //elasticsearch-sql支持的sql語句
						Map.class);//返回的文檔封裝對象類型
		//獲取結果對象列表
		List<Map> demos = esDatas.getDatas();

		//獲取總記錄數
		long totalSize = esDatas.getTotalSize();
		System.out.println(totalSize);
	}

開發交流

elasticsearch技術交流:166471282

elasticsearch:

bbossgroups

相關文章
相關標籤/搜索