文档章节

Elasticsearch SQL ORM查询案例介绍

bboss
 bboss
发布于 2018/10/17 10:08
字数 2750
阅读 2863
收藏 14

bboss ES SQL是针对es jdbc的替代解决方案

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

bboss 提供一组sql和fetchQuery API,可替代官方es jdbc模块;采用bboss即可拥有bboss的客户端自动发现和容灾能力、对es、jdk、spring boot的兼容性能力,又可以拥有es jdbc的所有功能,同时还解决了因为引入es jdbc导致项目对es版本的强依赖和兼容性问题,参考demo:

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

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

目前官方es sql提供的功能有限,也可以在bboss中使用Elasticsearch-sql插件提供的功能,下面有专门的章节介绍。

本文详细说明上面的案例:

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;
	}
}

实体定义说明:

通过column指定索引文档和对象属性的映射关系,指定日期格式和时区信息,示例如下:

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

指定属性的映射关系、日期格式和时区信息,示例如下:    

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

执行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

© 著作权归作者所有

bboss

bboss

粉丝 125
博文 62
码字总数 71419
作品 9
长沙
程序员
私信 提问
bboss es 5.0.3.9.1 发布,高性能Elasticsearch ORM开发库

高性能Elasticsearch ORM开发库bboss es 5.0.3.9.1发布 bboss es是一款基于query dsl语法的Elasticsearch ORM开发库,底层基于http restful。使用bboss es,可以快速编写出访问和操作elastic...

bboss
2018/01/30
2.3K
4
Elasticsearch JDBC案例介绍

The best elasticsearch highlevel java rest api-----bboss Elasticsearch 6.3以后的版本可以通过jdbc操作es,该功能还在不断的完善当中,本文介绍es jdbc使用方法。 1.首先在工程中导入es ...

bboss
2018/09/30
2.3K
0
高性能Elasticsearch ORM开发库bboss es 5.0.3.7.8发布

bboss es v5.0.3.7.8已发布。bboss elasticsearch是一套基于query dsl语法操作访问分布式搜索引擎elasticsearch的o/r mapping开发库,底层基于es restful api。使用bboss es,可以快速编写出...

bboss
2017/11/16
2.2K
4
bboss v5.2.1 发布,Elasticsearch Rest Client

The best Elasticsearch Highlevel Rest Client API-----bboss v5.2.1 发布。 主要功能特色 ElasticSearch兼容性:2.x,5.x,6.x,+ JDK兼容性: jdk 1.7+ Spring boot兼容性:1.x,2.x ORM和DSL二......

bboss
2018/11/27
682
2
bboss elasticsearch v5.0.6.2 发布

The best elasticsearch highlevel java rest api-----bboss bboss elasticsearch v5.0.6.2 发布 v5.0.6.2新增功能及改进: 1.升级最新的bboss版本到5.0.5.7 2.新增bboss es rest boot模块,......

bboss
2018/04/29
707
1

没有更多内容

加载失败,请刷新页面

加载更多

redis 内存信息解析

used_memory:由 Redis 分配器分配的内存总量,包含了redis进程内部的开销和数据占用的内存,以字节(byte)为单位 used_memory_rss:向操作系统申请的内存大小。与 top 、 ps等命令的输出一...

Canaan_
17分钟前
2
0
windows 下 python3 安装 pip setuptools

本文链接:https://blog.csdn.net/huzuxing/article/details/80807744 最近在家使用python的时候,总是报setuptools 模块未找到,于是在网上搜索了相关解决办法,但是都没有解决问题。 于是去...

开源中国首席CYO
23分钟前
2
0
数据库添加索引

mysql索引添加 navicat 步骤 - 选择表 -> 设计表 ->索引

以谁为师
33分钟前
3
0
java7与java9中的try-finally关闭资源

1.java7中的try 在java7之前,对于一些需要使用finally关闭资源的操作,会显得很臃肿. try{//}catch(Exception e){//}finally{if(xxxx != null){xxxx.close();}} 在jav...

Blueeeeeee
35分钟前
2
0
字节序转换详解

在跨平台和网络编程中我们经常会提到网络字节序和主机字节序,如果没有正确对两者进行转换,从而导致两方产生了不同的解释,就会出现意想不到的bug。 目录 0x01 概念 0x02 分类 0x03 两种字节...

无心的梦呓
45分钟前
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部