|
@@ -1,7 +1,7 @@
|
|
|
-SQL to DSL for Elasticsearch
|
|
|
|
|
|
|
+elasticsearch-query-tookit
|
|
|
====================================
|
|
====================================
|
|
|
|
|
|
|
|
-elasticsearch-sql2dsl版本
|
|
|
|
|
|
|
+版本
|
|
|
-------------
|
|
-------------
|
|
|
|
|
|
|
|
sql2dsl version | ES version
|
|
sql2dsl version | ES version
|
|
@@ -10,587 +10,121 @@ master | 2.4.4
|
|
|
2.x | 2.4.4
|
|
2.x | 2.4.4
|
|
|
1.x | 1.4.5
|
|
1.x | 1.4.5
|
|
|
|
|
|
|
|
-sql2dsl介绍
|
|
|
|
|
|
|
+介绍
|
|
|
-------------
|
|
-------------
|
|
|
-> `elasticsearch-sql2dsl`是一款能将SQL转换为ES的查询语言DSL的工具包,目前只支持比较简单的查询。
|
|
|
|
|
|
|
+> `elasticsearch-query-tookit`是一款elasticsearch查询编程工具包,提供Java编程接口,支持SQL解析生成DSL,支持JDBC驱动,支持和spring、ibatis集成
|
|
|
|
|
|
|
|
|
|
|
|
|
-使用注意
|
|
|
|
|
-------
|
|
|
|
|
-> * 在SQL的where条件中,原子条件的左边必须为变量名,右边必须为查询参数值
|
|
|
|
|
-> * 针对`Inner Doc`,直接引用即可:`a.b.c.d`
|
|
|
|
|
-> * 针对`Nested Doc`,需要在内嵌文档加上`$`符号: `$b.c`
|
|
|
|
|
|
|
+## 一、SQL解析生成DSL使用示例
|
|
|
|
|
|
|
|
-## Api使用示例
|
|
|
|
|
|
|
|
|
|
-常规sql查询,不带参数
|
|
|
|
|
```java
|
|
```java
|
|
|
-String sql = "select * from index.order where status='SUCCESS' order by nvl(pride, 0) asc limit 0, 20";
|
|
|
|
|
|
|
+String sql = "select * from index.order where status='SUCCESS' order by nvl(pride, 0) asc routing by 'JD' limit 0, 20";
|
|
|
|
|
|
|
|
ElasticSql2DslParser sql2DslParser = new ElasticSql2DslParser();
|
|
ElasticSql2DslParser sql2DslParser = new ElasticSql2DslParser();
|
|
|
//解析SQL
|
|
//解析SQL
|
|
|
ElasticSqlParseResult parseResult = sql2DslParser.parse(sql);
|
|
ElasticSqlParseResult parseResult = sql2DslParser.parse(sql);
|
|
|
-
|
|
|
|
|
//生成DSL,可用于rest api调用
|
|
//生成DSL,可用于rest api调用
|
|
|
String dsl = parseResult.toDsl();
|
|
String dsl = parseResult.toDsl();
|
|
|
|
|
|
|
|
//toRequest方法接收一个clinet对象参数,用于生成SearchRequestBuilder
|
|
//toRequest方法接收一个clinet对象参数,用于生成SearchRequestBuilder
|
|
|
SearchRequestBuilder searchReq = parseResult.toRequest(esClient);
|
|
SearchRequestBuilder searchReq = parseResult.toRequest(esClient);
|
|
|
-
|
|
|
|
|
-//执行查询
|
|
|
|
|
-SearchResponse response = searchReq.execute().actionGet();
|
|
|
|
|
-```
|
|
|
|
|
-指定可变参数查询
|
|
|
|
|
-```java
|
|
|
|
|
-String sql = "select * from index.order where status=? order by nvl(pride, 0) asc limit ?, ?";
|
|
|
|
|
-
|
|
|
|
|
-ElasticSql2DslParser sql2DslParser = new ElasticSql2DslParser();
|
|
|
|
|
-//指定参数,解析SQL
|
|
|
|
|
-ElasticSqlParseResult parseResult = sql2DslParser.parse(sql, new Object[]{"SUCCESS", 0, 20});
|
|
|
|
|
-
|
|
|
|
|
-//生成DSL,可用于rest api调用
|
|
|
|
|
-String dsl = parseResult.toDsl();
|
|
|
|
|
-
|
|
|
|
|
-//toRequest方法接收一个clinet对象参数,用于生成SearchRequestBuilder
|
|
|
|
|
-SearchRequestBuilder searchReq = parseResult.toRequest(esClient);
|
|
|
|
|
-
|
|
|
|
|
//执行查询
|
|
//执行查询
|
|
|
SearchResponse response = searchReq.execute().actionGet();
|
|
SearchResponse response = searchReq.execute().actionGet();
|
|
|
```
|
|
```
|
|
|
|
|
|
|
|
-向WHERE条件解析时注册监听
|
|
|
|
|
-```java
|
|
|
|
|
-String sql = "select * from index.order where status='SUCCESS' and lastUpdateTime > '2017-01-02' order by nvl(pride, 0) asc limit 0, 20";
|
|
|
|
|
-
|
|
|
|
|
-ElasticSql2DslParser sql2DslParser = new ElasticSql2DslParser();
|
|
|
|
|
-
|
|
|
|
|
-//指定SQL解析监听器,解析SQL
|
|
|
|
|
-ElasticSqlParseResult parseResult = sql2DslParser.parse(sql, new ParseActionListenerAdapter() {
|
|
|
|
|
- @Override
|
|
|
|
|
- public void onAtomConditionParse(ElasticSqlQueryField paramName, Object[] paramValues, SQLConditionOperator operator) {
|
|
|
|
|
- if(paramName.getQueryFieldType() == QueryFieldType.RootDocField && "lastUpdateTime".equals(paramName.getQueryFieldFullName())) {
|
|
|
|
|
- //这里是解析SQL中原子条件时的回调方法
|
|
|
|
|
- //某些按时间划分的索引,可在此解析出SQL中指定的时间范围,并重新设置需要查询的索引
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-});
|
|
|
|
|
-
|
|
|
|
|
-//生成DSL,可用于rest api调用
|
|
|
|
|
-String dsl = parseResult.toDsl();
|
|
|
|
|
-
|
|
|
|
|
-//toRequest方法接收一个clinet对象参数,用于生成SearchRequestBuilder
|
|
|
|
|
-SearchRequestBuilder searchReq = parseResult.toRequest(esClient);
|
|
|
|
|
-
|
|
|
|
|
-//执行查询
|
|
|
|
|
-SearchResponse response = searchReq.execute().actionGet();
|
|
|
|
|
-
|
|
|
|
|
-```
|
|
|
|
|
-使用routing by指定routing参数
|
|
|
|
|
-```bash
|
|
|
|
|
-String sql = "select * from index.order where status='SUCCESS' order by nvl(pride, 0) asc routing by 'A','B' limit 0, 20";
|
|
|
|
|
-
|
|
|
|
|
-ElasticSql2DslParser sql2DslParser = new ElasticSql2DslParser();
|
|
|
|
|
-//解析SQL,
|
|
|
|
|
-ElasticSqlParseResult parseResult = sql2DslParser.parse(sql);
|
|
|
|
|
-
|
|
|
|
|
-//toRequest方法会把指定的routing参数放到SearchRequest中
|
|
|
|
|
-SearchRequestBuilder searchReq = parseResult.toRequest(esClient);
|
|
|
|
|
-```
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-## SQL使用示例
|
|
|
|
|
-下面index表示索引名,order表示文档类型名
|
|
|
|
|
-```bash
|
|
|
|
|
-select * from index.order
|
|
|
|
|
-
|
|
|
|
|
-# 1. 默认从第0条数据开始,取15条
|
|
|
|
|
-# 2. 因为没有带where条件所以查询是match_all
|
|
|
|
|
-{
|
|
|
|
|
- "from" : 0,
|
|
|
|
|
- "size" : 15,
|
|
|
|
|
- "query" : {
|
|
|
|
|
- "match_all" : { }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-```
|
|
|
|
|
-
|
|
|
|
|
-用关键字limit指定分页参数
|
|
|
|
|
-```bash
|
|
|
|
|
-select * from index.order limit 0,100
|
|
|
|
|
-
|
|
|
|
|
-# 分页参数从0开始取100条
|
|
|
|
|
-{
|
|
|
|
|
- "from" : 0,
|
|
|
|
|
- "size" : 100,
|
|
|
|
|
- "query" : {
|
|
|
|
|
- "match_all" : { }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-```
|
|
|
|
|
-
|
|
|
|
|
-SQL中指定查询条件 status = 'SUCCESS'
|
|
|
|
|
-```bash
|
|
|
|
|
-select * from index.order where status='SUCCESS' limit 0,100
|
|
|
|
|
-
|
|
|
|
|
-{
|
|
|
|
|
- "from" : 0,
|
|
|
|
|
- "size" : 100,
|
|
|
|
|
- "query" : {
|
|
|
|
|
- "bool" : {
|
|
|
|
|
- "filter" : {
|
|
|
|
|
- "bool" : {
|
|
|
|
|
- "must" : {
|
|
|
|
|
- "term" : {
|
|
|
|
|
- "status" : "SUCCESS"
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-```
|
|
|
|
|
-
|
|
|
|
|
-范围查询 totalPrice > 1000
|
|
|
|
|
-```bash
|
|
|
|
|
-select * from index.order where status='SUCCESS' and totalPrice > 1000 limit 0,100
|
|
|
|
|
-
|
|
|
|
|
-{
|
|
|
|
|
- "from" : 0,
|
|
|
|
|
- "size" : 100,
|
|
|
|
|
- "query" : {
|
|
|
|
|
- "bool" : {
|
|
|
|
|
- "filter" : {
|
|
|
|
|
- "bool" : {
|
|
|
|
|
- "must" : [ {
|
|
|
|
|
- "term" : {
|
|
|
|
|
- "status" : "SUCCESS"
|
|
|
|
|
- }
|
|
|
|
|
- }, {
|
|
|
|
|
- "range" : {
|
|
|
|
|
- "totalPrice" : {
|
|
|
|
|
- "from" : 1000,
|
|
|
|
|
- "to" : null,
|
|
|
|
|
- "include_lower" : false,
|
|
|
|
|
- "include_upper" : true
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- } ]
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-```
|
|
|
|
|
-
|
|
|
|
|
-使用 between...and... 指定条件范围(上下限都取)
|
|
|
|
|
-```bash
|
|
|
|
|
-select * from index.order where status='SUCCESS' and totalPrice between 1000 and 2000 limit 0,100
|
|
|
|
|
|
|
|
|
|
-{
|
|
|
|
|
- "from" : 0,
|
|
|
|
|
- "size" : 100,
|
|
|
|
|
- "query" : {
|
|
|
|
|
- "bool" : {
|
|
|
|
|
- "filter" : {
|
|
|
|
|
- "bool" : {
|
|
|
|
|
- "must" : [ {
|
|
|
|
|
- "term" : {
|
|
|
|
|
- "status" : "SUCCESS"
|
|
|
|
|
- }
|
|
|
|
|
- }, {
|
|
|
|
|
- "range" : {
|
|
|
|
|
- "totalPrice" : {
|
|
|
|
|
- "from" : 1000,
|
|
|
|
|
- "to" : 2000,
|
|
|
|
|
- "include_lower" : true,
|
|
|
|
|
- "include_upper" : true
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- } ]
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-```
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-日期类型范围查询,下面3条SQL等效
|
|
|
|
|
|
|
+## 二、集成IBatis、Spring
|
|
|
|
|
+首先在Spring配置文件中增加如下代码
|
|
|
|
|
+1. 指定driverClassName:org.elasticsearch.jdbc.ElasticDriver
|
|
|
|
|
+2. 指定连接ES的连接串:jdbc:elastic:192.168.0.109:9300/product_cluster
|
|
|
|
|
+3. 创建一个SqlMapClient对象,并指定sqlMapConfig.xml路径
|
|
|
```bash
|
|
```bash
|
|
|
-select * from index.order where status='SUCCESS' and lastUpdateTime > '2017-01-01 00:00:00' limit 0,100
|
|
|
|
|
-select * from index.order where status='SUCCESS' and lastUpdateTime > '2017-01-01' limit 0,100
|
|
|
|
|
-
|
|
|
|
|
-#日期函数可以自定义日期格式
|
|
|
|
|
-select * from index.order where status='SUCCESS' and lastUpdateTime > date('yyyy-MM-dd', '2017-01-01') limit 0,100
|
|
|
|
|
-
|
|
|
|
|
-{
|
|
|
|
|
- "from" : 0,
|
|
|
|
|
- "size" : 100,
|
|
|
|
|
- "query" : {
|
|
|
|
|
- "bool" : {
|
|
|
|
|
- "filter" : {
|
|
|
|
|
- "bool" : {
|
|
|
|
|
- "must" : [ {
|
|
|
|
|
- "term" : {
|
|
|
|
|
- "status" : "SUCCESS"
|
|
|
|
|
- }
|
|
|
|
|
- }, {
|
|
|
|
|
- "range" : {
|
|
|
|
|
- "lastUpdateTime" : {
|
|
|
|
|
- "from" : "2017-01-01T00:00:00.000+0800",
|
|
|
|
|
- "to" : null,
|
|
|
|
|
- "include_lower" : false,
|
|
|
|
|
- "include_upper" : true
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- } ]
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
|
|
+<bean id="elasticDataSource" class="org.elasticsearch.jdbc.ElasticSingleConnectionDataSource" destroy-method="destroy">
|
|
|
|
|
+ <property name="driverClassName" value="org.elasticsearch.jdbc.ElasticDriver" />
|
|
|
|
|
+ <property name="url" value="jdbc:elastic:192.168.0.109:9300/product_cluster" />
|
|
|
|
|
+</bean>
|
|
|
|
|
|
|
|
|
|
+<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
|
|
|
|
|
+ <property name="dataSource" ref="elasticDataSource" />
|
|
|
|
|
+ <property name="configLocation" value="classpath:sqlMapConfig.xml"/>
|
|
|
|
|
+</bean>
|
|
|
```
|
|
```
|
|
|
|
|
|
|
|
-排序条件,price升序,publishDate降序
|
|
|
|
|
|
|
+sqlMapConfig.xml文件内容如下:
|
|
|
```bash
|
|
```bash
|
|
|
-select * from index.order where status='SUCCESS' order by price asc, publishDate desc
|
|
|
|
|
|
|
+<sqlMapConfig>
|
|
|
|
|
+ <settings
|
|
|
|
|
+ cacheModelsEnabled="true"
|
|
|
|
|
+ lazyLoadingEnabled="true"
|
|
|
|
|
+ enhancementEnabled="true"
|
|
|
|
|
+ maxSessions="64"
|
|
|
|
|
+ maxTransactions="20"
|
|
|
|
|
+ maxRequests="128"
|
|
|
|
|
+ useStatementNamespaces="true"/>
|
|
|
|
|
|
|
|
-{
|
|
|
|
|
- "from" : 0,
|
|
|
|
|
- "size" : 15,
|
|
|
|
|
- "query" : {
|
|
|
|
|
- "bool" : {
|
|
|
|
|
- "filter" : {
|
|
|
|
|
- "bool" : {
|
|
|
|
|
- "must" : {
|
|
|
|
|
- "term" : {
|
|
|
|
|
- "status" : "SUCCESS"
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- "sort" : [ {
|
|
|
|
|
- "price" : {
|
|
|
|
|
- "order" : "asc"
|
|
|
|
|
- }
|
|
|
|
|
- }, {
|
|
|
|
|
- "publishDate" : {
|
|
|
|
|
- "order" : "desc"
|
|
|
|
|
- }
|
|
|
|
|
- } ]
|
|
|
|
|
-}
|
|
|
|
|
|
|
+ <sqlMap resource="sqlmap/PRODUCT.xml"/>
|
|
|
|
|
|
|
|
|
|
+</sqlMapConfig>
|
|
|
```
|
|
```
|
|
|
|
|
|
|
|
-使用nvl函数指定默认值
|
|
|
|
|
|
|
+PRODUCT.xml文件中声明select sql语句
|
|
|
```bash
|
|
```bash
|
|
|
-select * from index.order where status='SUCCESS' order by nvl(price, 0) asc, publishDate desc
|
|
|
|
|
-
|
|
|
|
|
-{
|
|
|
|
|
- "from" : 0,
|
|
|
|
|
- "size" : 15,
|
|
|
|
|
- "query" : {
|
|
|
|
|
- "bool" : {
|
|
|
|
|
- "filter" : {
|
|
|
|
|
- "bool" : {
|
|
|
|
|
- "must" : {
|
|
|
|
|
- "term" : {
|
|
|
|
|
- "status" : "SUCCESS"
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- "sort" : [ {
|
|
|
|
|
- "price" : {
|
|
|
|
|
- "order" : "asc",
|
|
|
|
|
- "missing" : 0
|
|
|
|
|
- }
|
|
|
|
|
- }, {
|
|
|
|
|
- "publishDate" : {
|
|
|
|
|
- "order" : "desc"
|
|
|
|
|
- }
|
|
|
|
|
- } ]
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
|
|
+<sqlMap namespace="PRODUCT">
|
|
|
|
|
+ <select id="getProductByCodeAndMatchWord" parameterClass="java.util.Map" resultClass="java.lang.String">
|
|
|
|
|
+ SELECT *
|
|
|
|
|
+ FROM index.product
|
|
|
|
|
+ QUERY match(productName, #matchWord#) or prefix(productName, #prefixWord#, 'boost:2.0f')
|
|
|
|
|
+ WHERE productCode = #productCode#
|
|
|
|
|
+ AND advicePrice > #advicePrice#
|
|
|
|
|
+ AND $$buyers.buyerName IN ('china', 'usa')
|
|
|
|
|
+ ROUTING BY #routingVal#
|
|
|
|
|
+ </select>
|
|
|
|
|
+</sqlMap>
|
|
|
```
|
|
```
|
|
|
|
|
|
|
|
-内嵌文档排序,指定sort_mode(其中$providers 表示内嵌文档),按照 min 方式排序
|
|
|
|
|
-```bash
|
|
|
|
|
-select * from index.order where status='SUCCESS' order by nvl(product.$providers.sortNo, 0, 'min') asc, publishDate desc
|
|
|
|
|
|
|
|
|
|
-{
|
|
|
|
|
- "from" : 0,
|
|
|
|
|
- "size" : 15,
|
|
|
|
|
- "query" : {
|
|
|
|
|
- "bool" : {
|
|
|
|
|
- "filter" : {
|
|
|
|
|
- "bool" : {
|
|
|
|
|
- "must" : {
|
|
|
|
|
- "term" : {
|
|
|
|
|
- "status" : "SUCCESS"
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- "sort" : [ {
|
|
|
|
|
- "product.providers.sortNo" : {
|
|
|
|
|
- "order" : "asc",
|
|
|
|
|
- "missing" : 0,
|
|
|
|
|
- "mode" : "min",
|
|
|
|
|
- "nested_path" : "product.providers"
|
|
|
|
|
- }
|
|
|
|
|
- }, {
|
|
|
|
|
- "publishDate" : {
|
|
|
|
|
- "order" : "desc"
|
|
|
|
|
- }
|
|
|
|
|
- } ]
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-```
|
|
|
|
|
-
|
|
|
|
|
-Inner Doc 查询
|
|
|
|
|
|
|
+编写对应DAO代码:
|
|
|
```bash
|
|
```bash
|
|
|
-select * from index.order where seller.name='JD' order by id desc
|
|
|
|
|
-
|
|
|
|
|
-{
|
|
|
|
|
- "from" : 0,
|
|
|
|
|
- "size" : 15,
|
|
|
|
|
- "query" : {
|
|
|
|
|
- "bool" : {
|
|
|
|
|
- "filter" : {
|
|
|
|
|
- "bool" : {
|
|
|
|
|
- "must" : {
|
|
|
|
|
- "term" : {
|
|
|
|
|
- "seller.name" : "JD"
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- "sort" : [ {
|
|
|
|
|
- "id" : {
|
|
|
|
|
- "order" : "desc"
|
|
|
|
|
- }
|
|
|
|
|
- } ]
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-```
|
|
|
|
|
|
|
+@Repository
|
|
|
|
|
+public class ProductDao {
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ @Qualifier("sqlMapClient")
|
|
|
|
|
+ private SqlMapClient sqlMapClient;
|
|
|
|
|
|
|
|
-Nested Doc查询($providers 表示内嵌文档)
|
|
|
|
|
-```bash
|
|
|
|
|
-select * from index.order where product.$providers.name in ('JD', 'TB') and product.price < 1000 order by id desc
|
|
|
|
|
|
|
|
|
|
-{
|
|
|
|
|
- "from" : 0,
|
|
|
|
|
- "size" : 15,
|
|
|
|
|
- "query" : {
|
|
|
|
|
- "bool" : {
|
|
|
|
|
- "filter" : {
|
|
|
|
|
- "bool" : {
|
|
|
|
|
- "must" : [ {
|
|
|
|
|
- "range" : {
|
|
|
|
|
- "product.price" : {
|
|
|
|
|
- "from" : null,
|
|
|
|
|
- "to" : 1000,
|
|
|
|
|
- "include_lower" : true,
|
|
|
|
|
- "include_upper" : false
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }, {
|
|
|
|
|
- "nested" : {
|
|
|
|
|
- "filter" : {
|
|
|
|
|
- "terms" : {
|
|
|
|
|
- "product.providers.name" : [ "JD", "TB" ]
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- "path" : "product.providers"
|
|
|
|
|
- }
|
|
|
|
|
- } ]
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- "sort" : [ {
|
|
|
|
|
- "id" : {
|
|
|
|
|
- "order" : "desc"
|
|
|
|
|
- }
|
|
|
|
|
- } ]
|
|
|
|
|
-}
|
|
|
|
|
-```
|
|
|
|
|
|
|
+ public List<Product> getProductByCodeAndMatchWord(String matchWord, String productCode) throws SQLException {
|
|
|
|
|
+ Map<String, Object> paramMap = Maps.newHashMap();
|
|
|
|
|
+ paramMap.put("productCode", productCode);
|
|
|
|
|
+ paramMap.put("advicePrice", 1000);
|
|
|
|
|
+ paramMap.put("routingVal", "A");
|
|
|
|
|
+ paramMap.put("matchWord", matchWord);
|
|
|
|
|
+ paramMap.put("prefixWord", matchWord);
|
|
|
|
|
+ String responseGson = (String) sqlMapClient.queryForObject("PRODUCT.getProductByCodeAndMatchWord", paramMap);
|
|
|
|
|
|
|
|
|
|
+ JdbcSearchResponseResolver responseResolver = new JdbcSearchResponseResolver(responseGson);
|
|
|
|
|
+ JdbcSearchResponse<Product> searchResponse = responseResolver.resolveSearchResponse(Product.class);
|
|
|
|
|
|
|
|
-组合条件查询
|
|
|
|
|
-```bash
|
|
|
|
|
-select * from index.order
|
|
|
|
|
-where
|
|
|
|
|
-(product.$providers.name in ('JD', 'TB') or product.$providers.channel='ONLINE')
|
|
|
|
|
-and
|
|
|
|
|
-(product.status='OPEN' or product.price < 1000)
|
|
|
|
|
-order by id desc
|
|
|
|
|
|
|
+ return searchResponse.getDocList();
|
|
|
|
|
|
|
|
-{
|
|
|
|
|
- "from" : 0,
|
|
|
|
|
- "size" : 15,
|
|
|
|
|
- "query" : {
|
|
|
|
|
- "bool" : {
|
|
|
|
|
- "filter" : {
|
|
|
|
|
- "bool" : {
|
|
|
|
|
- "must" : [ {
|
|
|
|
|
- "bool" : {
|
|
|
|
|
- "should" : {
|
|
|
|
|
- "nested" : {
|
|
|
|
|
- "filter" : {
|
|
|
|
|
- "bool" : {
|
|
|
|
|
- "should" : [ {
|
|
|
|
|
- "terms" : {
|
|
|
|
|
- "product.providers.name" : [ "JD", "TB" ]
|
|
|
|
|
- }
|
|
|
|
|
- }, {
|
|
|
|
|
- "term" : {
|
|
|
|
|
- "product.providers.channel" : "ONLINE"
|
|
|
|
|
- }
|
|
|
|
|
- } ]
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- "path" : "product.providers"
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }, {
|
|
|
|
|
- "bool" : {
|
|
|
|
|
- "should" : [ {
|
|
|
|
|
- "term" : {
|
|
|
|
|
- "product.status" : "OPEN"
|
|
|
|
|
- }
|
|
|
|
|
- }, {
|
|
|
|
|
- "range" : {
|
|
|
|
|
- "product.price" : {
|
|
|
|
|
- "from" : null,
|
|
|
|
|
- "to" : 1000,
|
|
|
|
|
- "include_lower" : true,
|
|
|
|
|
- "include_upper" : false
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- } ]
|
|
|
|
|
- }
|
|
|
|
|
- } ]
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
}
|
|
}
|
|
|
- },
|
|
|
|
|
- "sort" : [ {
|
|
|
|
|
- "id" : {
|
|
|
|
|
- "order" : "desc"
|
|
|
|
|
- }
|
|
|
|
|
- } ]
|
|
|
|
|
}
|
|
}
|
|
|
```
|
|
```
|
|
|
-
|
|
|
|
|
-查询字段指定
|
|
|
|
|
|
|
+编写测试方法
|
|
|
```bash
|
|
```bash
|
|
|
-select totalPrice, product.*, product.$seller.* from index.order
|
|
|
|
|
-
|
|
|
|
|
-{
|
|
|
|
|
- "from" : 0,
|
|
|
|
|
- "size" : 15,
|
|
|
|
|
- "query" : {
|
|
|
|
|
- "match_all" : { }
|
|
|
|
|
- },
|
|
|
|
|
- "_source" : {
|
|
|
|
|
- "includes" : [ "totalPrice", "product.*", "product.seller.*" ],
|
|
|
|
|
- "excludes" : [ ]
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-```
|
|
|
|
|
|
|
+@Test
|
|
|
|
|
+public void testProductQuery() throws Exception {
|
|
|
|
|
+ BeanFactory factory = new ClassPathXmlApplicationContext("application-context.xml");
|
|
|
|
|
|
|
|
|
|
+ ProductDao productDao = factory.getBean(ProductDao.class);
|
|
|
|
|
|
|
|
|
|
+ List<Product> productList = productDao.getProductByCodeAndMatchWord("iphone 6s", "IP_6S");
|
|
|
|
|
|
|
|
-
|
|
|
|
|
-聚合统计,目前只支持 terms,range 聚合
|
|
|
|
|
-
|
|
|
|
|
-```bash
|
|
|
|
|
-select min(price),avg(price) from index.product group by terms(category),terms(color),range(price, segment(0,100), segment(100,200), segment(200,300))
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-{
|
|
|
|
|
- "from" : 0,
|
|
|
|
|
- "size" : 15,
|
|
|
|
|
- "query" : {
|
|
|
|
|
- "match_all" : { }
|
|
|
|
|
- },
|
|
|
|
|
- "aggregations" : {
|
|
|
|
|
- "agg_category" : {
|
|
|
|
|
- "terms" : {
|
|
|
|
|
- "field" : "category",
|
|
|
|
|
- "size" : 500,
|
|
|
|
|
- "shard_size" : 1000,
|
|
|
|
|
- "min_doc_count" : 1,
|
|
|
|
|
- "shard_min_doc_count" : 1,
|
|
|
|
|
- "order" : {
|
|
|
|
|
- "_count" : "desc"
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- "aggregations" : {
|
|
|
|
|
- "agg_color" : {
|
|
|
|
|
- "terms" : {
|
|
|
|
|
- "field" : "color",
|
|
|
|
|
- "size" : 500,
|
|
|
|
|
- "shard_size" : 1000,
|
|
|
|
|
- "min_doc_count" : 1,
|
|
|
|
|
- "shard_min_doc_count" : 1,
|
|
|
|
|
- "order" : {
|
|
|
|
|
- "_count" : "desc"
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- "aggregations" : {
|
|
|
|
|
- "agg_price" : {
|
|
|
|
|
- "range" : {
|
|
|
|
|
- "field" : "price",
|
|
|
|
|
- "ranges" : [ {
|
|
|
|
|
- "key" : "0-100",
|
|
|
|
|
- "from" : 0.0,
|
|
|
|
|
- "to" : 100.0
|
|
|
|
|
- }, {
|
|
|
|
|
- "key" : "100-200",
|
|
|
|
|
- "from" : 100.0,
|
|
|
|
|
- "to" : 200.0
|
|
|
|
|
- }, {
|
|
|
|
|
- "key" : "200-300",
|
|
|
|
|
- "from" : 200.0,
|
|
|
|
|
- "to" : 300.0
|
|
|
|
|
- } ]
|
|
|
|
|
- },
|
|
|
|
|
- "aggregations" : {
|
|
|
|
|
- "min_price" : {
|
|
|
|
|
- "min" : {
|
|
|
|
|
- "field" : "price"
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- "avg_price" : {
|
|
|
|
|
- "avg" : {
|
|
|
|
|
- "field" : "price"
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ for (Product product : productList) {
|
|
|
|
|
+ System.out.println(product.getProductName());
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
```
|
|
```
|
|
|
-
|
|
|
|
|
作者: [@陈楠][1]
|
|
作者: [@陈楠][1]
|
|
|
Email: 465360798@qq.com
|
|
Email: 465360798@qq.com
|
|
|
|
|
|