ES SQL使用说明文档

ES SQL使用说明文档

一、Elasticsearch术语介绍

l  接近实时(NRT):

Elasticsearch 是一个接近实时的搜索平台。这意味着,从索引一个文档直到这个文档能够被搜索到有一个很小的延迟,包括如果做了集群的话,集群中的各个节点数据同步也是接近实时的。

l  集群(cluster):

一组拥有共同的 cluster name 的节点。

l  节点(node):

集群中的一个 Elasticearch 实例。

l  索引(index):

ElasticSearch将它的数据存储在一个或多个索引(index)中。用SQL领域的术语来类比,索引就像数据库,可以向索引写入文档或者从索引中读取文档。

l  文档类型(type):

文档类型(type)是用来规定文档的各个字段内容的数据类型和其他的一些约束,相当于关系型数据库中的表,一个索引(index)可以有多个文档类型(type)。

l  文档(document):

一个文档(document)相当于关系型数据库中的一行数据。

l  字段(Field):

相当于数据库中的column。

l  映射(Mapping):

相当于数据库中的schema,用来约束字段的类型,映射可以被明确地定义,或者在一个文档被索引的时候自动生成。

l  分片(Shard):

索引的子集,索引可以切分成多个分片,分布到不同的集群节点上。分片对应的是 Lucene 中的索引。分片分为主分片(Primary shard)和副本分片(Replica shard)每个主分片可以有0个或者多个副本。

Elasticsearch与关系数据的类比对应关系如下:

Relational DB -> Databases -> Tables -> Rows -> Columns

关系型数据库  数据库     表      行     列

Elasticsearch -> Indices  ->  Types -> Documents -> Fields

Elasticsearch   索引       类型     文档      域(字段)

 

由于Elasticsearch的查询语言(DSL)比较复杂,学习成本高。因此推荐使用第三方插件Elasticsearch-SQL,可用sql查询Elasticsearch,语法跟关系型数据库的sql有一些不同。

注意:使用Elasticsearch-SQL查询时:

1、在hue中查询时,select前不能有空格或者空行;

2、查询中字段名大小写敏感;

3、求个数时,不能用 count(1), 必须是count(*);

4、select 字段名,* from….时  后面的*不起作用;

5、目前支持中文字段查询,但不支持带特殊符号的字段作为where条件,例如不支持where 总订单数(条)>20;

6、两个整数类型字段相除时,得到的结果也是整数,此时至少一个字段需要化为小数(例如乘除1.0、加减0.0):

SELECT 慢充终端数,快充终端数,1.0*慢充终端数/快充终端数 as a

from etlddcharging

where 快充终端数>0 and 慢充终端数>0 limit 10

二、快速入门:

ES查询默认查询200条,最大查询10000条,可通过max_result_window修改。

1、查询index下的type:

SELECT fields from indexName WHERE conditions

SELECT fields from indexName/type WHERE conditions

SELECT fields from indexName/type1,indexName/type2 WHERE conditions

SELECT fields from indexName1,indexName2 WHERE conditions

--其中,fields前面不能使用别名或者table.:

select color,doubleValue from cars,test_wj limit 10 (正确)

select cars.color,test_wj.doubleValue from cars,test_wj limit 10 (错误)

2、使用别名:

ES-Sql字段支持使用别名,当select后面只有一个别名列,查询结果会列出所有的字段以及别名列,例如:

SELECT CityName as acity FROM mrp_userlabel LIMIT 10 ;

此时,若只想显示别名列,有两种解决方案:

l  使用exclude(*)排除其他列:

SELECT CityName as acity ,exclude(*) FROM mrp_userlabel LIMIT 10 ;

l  select后面添加一个非别名列,这相当于自动加了include,使结果只包含选择的列名:

SELECT CityCode,CityName as acity FROM mrp_userlabel LIMIT 10 ;

3、分页查询:

SELECT * from mrp_userlabel limit 10,20

其中limit后面第一个参数是from,表示目标数据的偏移值,第二个参数是size,表示数据条数。以上查询第10到第30条数据[l1] 。但是ES最大查询默认max_result_window =10000条,当 from + size > max_result_window 时,es 将返回错误。

4、计算列--可以加减乘除固定数值,也可以两个字段之间进行加减乘除:

SELECT CharPower,CharMoneyEC,CharMoneySC,

CharPower + 2 as a,

CharPower - 2 as b,

CharPower * 2 as c,

CharPower / 2 as d,

CharPower % 2 as e,

CharMoneyEC + CharMoneySC as f,

CharMoneyEC - CharMoneySC as g,

CharMoneyEC * CharMoneySC as h,

CharMoneyEC / CharMoneySC as i,

CharMoneyEC % CharMoneySC as j

from mrp_userlabel where CityCode<>'11' limit 10

注意:两个整数类型字段相除时,得到的结果也是整数,此时至少一个字段需要化为小数(例如乘除1.0、加减0.0):

SELECT 慢充终端数,快充终端数,

1.0*慢充终端数/快充终端数 as a,慢充终端数/快充终端数 as b

from etlddcharging

where 快充终端数>0 and 慢充终端数>0 limit 10

 

5、数字范围过滤--大于等于小于运算:

l  字段跟固定数值之间的运算:

SELECT *

from mrp_userlabel

where  CharPower > 0.9 and CharPower < 2.1 and CityName='北京市'

limit 10;

l  字段之间的运算1:【此时where后面只能跟一个条件,多了会报错】

 

解决方案:

SELECT CharMoney,CharMoneySC,CharPower FROM mrp_userlabel where script('doc["CharMoney"].value>doc["CharMoneySC"].value && doc["CharPower"].value>0.9')

limit 10;

或者

SELECT CharMoney,CharMoneySC,CharPower FROM mrp_userlabel where script('doc["CharMoney"].value>doc["CharMoneySC"].value') and CharPower > 0.9

limit 10;

-- script语法详见【6.1 Script基本用法:】

l  字段之间的运算2:【以下不支持】

 

解决方案:

SELECT CharMoney,CharMoneySC FROM mrp_userlabel where script('doc["CharMoney"].value+doc["CharMoneySC"].value>20')

limit 10 -- script语法详见【6.1 Script基本用法:】

6、查询日期字段:

见【3.2 函数支持】,使用date_format函数,支持传递时区。

7、group by分组,详情见【3.3 聚合】:

l  group by 一个字段:

SELECT COUNT(*) FROM mrp_userlabel GROUP BY CityName;

l  group by多个字段且使用limit时,需要使用terms(原因见【3.3.2.1 terms聚合】):

SELECT COUNT(*) FROM mrp_userlabel

GROUP BY terms(field='CityName',size='10000',alias='CityName'),

terms(field='MarketName',size='10000',alias='MarketName')

limit 10000;

l  按照日期分组,使用date_histogram聚合,可以指定日期格式以及时区(具体用法见【3.3.2.3 日期直方图(date histogram)聚合】):

SELECT count(*) FROM ChargeBillWideTable GROUP BY date_histogram(field='BeginTime','interval'='1d','alias'='yourAlias', 'format'='yyyy-MM-dd', 'time_zone'='+08:00', 'min_doc_count'=1,order='desc')

8、in或者not in用法:

某字段in一组值内时,in后面只能跟1024个值,超过会报错,可用IN_TERMS[l2] 代替in:

SELECT MarketName,CityName,DataTime, CustID

FROM mrp_userlabel 

WHERE DataTime='2018-10-31T16:00:00.000Z'

and MarketName ='青岛特来电汽车充电有限公司'

and LabelLevel3 ='高价值用户'

and not CustID = IN_TERMS(

  SELECT  distinct CustID FROM mrp_userlabel 

WHERE DataTime='2018-09-30T16:00:00.000Z'

and MarketName ='青岛特来电汽车充电有限公司'

and LabelLevel3 ='高价值用户'

limit 2000

)

ORDER BY MarketName asc,CityName asc,DataTime asc

LIMIT 10000;

三、基本用法

3.1. 基本查询以及条件

l  基本查询语法为:

SELECT fields from indexName WHERE conditions

l  查询一个index下的type:

SELECT fields from indexName/type WHERE conditions

l  也可以一次性查询一个index下的多个type:

SELECT fields from indexName/type1,indexName/type2 WHERE conditions

l  也可以一次性查询多个index:

SELECT fields from indexName1,indexName2 WHERE conditions

--其中,fields前面不能使用别名或者table.:

select color,doubleValue from cars,test_wj limit 10 (正确)

select cars.color,test_wj.doubleValue from cars,test_wj limit 10 (错误)

3.1.1 SQL支持语句

  • SQL Select
  • SQL Delete(尚未开放)
  • SQL Where
  • SQL Order By
  • SQL Group By
  • SQL Limit (default is 200)

SELECT * FROM abnormalsoc_201801 WHERE PowerPerSoc > 0.9 LIMIT 10 ;

SELECT * FROM abnormalsoc_201801/abnormalsoc WHERE PowerPerSoc > 0.9 ORDER BY CanIndex DESC LIMIT 10 ;

SELECT * FROM abnormalsoc_201801 WHERE PowerPerSoc > 0.9 AND CtrlAddress = '42011700143' LIMIT 10 ;

3.1.2 SQL支持条件

  • SQL Like -(针对keyword类型字段,text类型字段不能使用like)
  • SQL AND & OR
  • SQL COUNT distinct
  • SQL In
  • SQL Between and
  • SQL Aliases
  • SQL NOT

SELECT count(distinct RelatedBillCode) FROM abnormalsoc_201801 where (CanIndex like '18%' or CanIndex like '19%') and CtrlAddress in ('42011700143','33011000371') limit 10;

SELECT * FROM test_wj where floatValue not Between 1.1 and 3.1 limit 10

--其中(Between 1.1 and 3.1)语法包括1.1、3.1。

 

3.1.3 SQL字段

字段可以按精确字段名称列出,也可以用通配符(*)[l3] 使用include/exclude语法。

  • include('d *') - 包括以“d”开头的所有字段
  • exclude('age') - 包括除“age”之外的所有字段
  • include('* Name'),exclude('lastName') - 包括以“name”结尾的所有字段,“lastName”除外。

SELECT CanIndex,include('*Flink*'),exclude('FlinkPorcessTimeTag')  FROM abnormalsoc_201801 LIMIT 10 ;

字段使用别名时:

ES-Sql字段支持使用别名,当select后面只有一个别名列,查询结果会列出所有的字段以及别名列,例如:

SELECT CityName as acity FROM mrp_userlabel LIMIT 10 ;

 

此时,若只想显示别名列,有两种解决方案:

1)使用exclude(*)排除其他列:

SELECT CityName as acity ,exclude(*) FROM mrp_userlabel LIMIT 10 ;

 

2)select后面添加一个非别名列,这相当于自动加了include,使结果只包含选择的列名:

SELECT CityCode,CityName as acity FROM mrp_userlabel LIMIT 10 ;

 

3.2 函数支持

支持以下函数:

l  Floor,向下取整;

l  Trim,删除字符串首尾的空格;

l  Log,数学上的对数函数,计算一个数字的自然对数;

l  log10,数学上的对数函数;计算以10为基数的对数;

l  substring,截取字符串;

l  round,四舍五入为整数;

l  sqrt,一个非负实数的平方根;

l  concat_ws,根据分隔符连接字符串;

l  +  加、- 减、* 乘、/ 除、% 取余、>大于、<小于、=等于、<> 不等于;

l  case when;

l  cast,支持INT, LONG, FLOAT, DOUBLE, STRING, DATETIME;

l  date_format,日期格式化。

并且:

l  select,groupBy支持函数和字段使用别名;

l  支持嵌套函数,例如,Trim(substring('newtype',0,3));

l  支持二元操作,例如,floor(substring(newtype,0,14)/100)/5)*5

date_format函数支持传入时区参数(不传时区,默认东八区),如下:

SELECT CreateTime, date_format(CreateTime,'yyyy-MM-dd HH') as aa, date_format(CreateTime,'yyyy-MM-dd HH','+0800') as bb, date_format(CreateTime,'yyyy-MM-dd HH','+0000') as cc

from datachangelog_201812 limit 10;

-- CreateTime是东八区时间,aa、bb是东八区时间,cc是UTC时间。

 

SELECT LastCharTime,date_format(LastCharTime,'yyyy-MM-dd HH') as aa,date_format(LastCharTime,'yyyy-MM-dd HH','+0800') as bb,date_format(LastCharTime,'yyyy-MM-dd HH','+0000') as cc from mrp_userlabel limit 10;

--LastCharTime是UTC时间,aa、bb取值是东八区时间,cc是UTC时间。

 

其他例子:

SELECT CityName,CharPower, trim(CityName) as a1,floor(CharPower) as a2,round(CharPower) as a3,sqrt(CharPower) as a4,log(CharPower) as a5,log10(CharPower) as a6

from mrp_userlabel;

 

SELECT CharPower,CharMoneyEC,CharMoneySC,

CharPower + 2 as a,

CharPower - 2 as b,

CharPower * 2 as c,

CharPower / 2 as d,

CharPower % 2 as e,

CharMoneyEC + CharMoneySC as f,

CharMoneyEC - CharMoneySC as g,

CharMoneyEC * CharMoneySC as h,

CharMoneyEC / CharMoneySC as i,

CharMoneyEC % CharMoneySC as j

from mrp_userlabel where CityCode<>'11' limit 10

 

SELECT MarketID,substring(MarketID,0,3) as aa,

CityCode,CityName,concat_ws(',',CityCode,CityName) as bb

from mrp_userlabel;

 

select CityCode,case when CityCode='11' then '北京市'  when CityCode='12'  then '天津市' else '其他' end as a

from  mrp_userlabel

limit 10

 

SELECT CityCode,DataTime, CAST(DataTime AS DATETIME) AS tt,cast(CityCode as INT)+1 as aa

from mrp_userlabel

limit 10;

3.3 聚合

3.3.1 Metrics(度量)

  • min
  • max
  • sum
  • count
  • avg

SELECT CanIndex,CtrlAddress, count(*),avg(PowerPerSoc), max(PowerPerSoc), min(PowerPerSoc),sum(PowerPerSoc)

FROM abnormalsoc_201801 group by CanIndex,CtrlAddress limit 10

  • stats(统计,查询结果包含:sum、avg、max、min、count基础度量):
  • percentiles(百分位数):
  • extended_stats(扩展统计,查询结果包含:方差、平方和、标准差、标准差界限以及max、avg等基础度量,注:只在数值型字段上使用):
SELECT stats(PowerPerSoc) FROM abnormalsoc_201801
SELECT percentiles(PowerPerSoc) FROM abnormalsoc_201801
SELECT extended_stats(PowerPerSoc) FROM abnormalsoc_201801

3.3.2 Buckets(桶)

3.3.2.1 terms聚合

l  group by一个字段:

SELECT COUNT(*) FROM mrp_userlabel GROUP BY CityName;

l  group by多个字段:

根据多个列进行group by时, select sum(x) from Table group by col1,col2 limit y 这种写法会造成结果不正确,因为limit只会加在第一个字段上,后面的字段会按照默认值,每个桶(bucket)默认返回10条数据,例如:

SELECT COUNT(*) FROM mrp_userlabel GROUP BY CityName, MarketName limit 10000;

这样所有的CityName,因为总数<10000,会被列出来,但每个CityName下最多返回10个MarketName,因为ES的默认桶返回值是10。解决方案为使用 group by terms()语法,正确写法:

SELECT COUNT(*) FROM mrp_userlabel

GROUP BY terms(field='CityName',size='10000',alias='CityName'),

terms(field='MarketName',size='10000',alias='MarketName')

limit 10000;

3.3.2.2 范围(range)聚合

字段后面跟上范围。例如,查询PowerPerSoc在0.5-1.0、1.0-2.0、2.0-3.0之间的数据条数:

SELECT COUNT(PowerPerSoc) FROM abnormalsoc_201801 GROUP BY range(PowerPerSoc, 0.5,1,2,3)

3.3.2.3 日期直方图(date histogram)聚合

设置时间字段(field)、区间('interval')、可选是否使用别名('alias')、时间格式('format')、时区('time_zone')、桶内最大数据条数('min_doc_count')、排序(order):

SELECT count(*) FROM ChargeBillWideTable GROUP BY date_histogram(field='BeginTime','interval'='1d','alias'='yourAlias', 'format'='yyyy-MM-dd', 'time_zone'='+08:00', 'min_doc_count'=1,order='desc')

3.3.2.4 日期范围(date range)聚合

设置字段以及带格式的区间,可选是否使用别名。

SELECT count(*) FROM mrp_userlabel GROUP BY date_range('alias'='yourAlias',field='DataTime','format'='yyyy-MM-dd' ,'2018-10-21','2018-10-22','now-7d','now-6d','now')

3.4 Union and Minus

实现Union & Minus,第一个查询字段名称应该与第二个查询字段名称一致,可以使用别名。

3.4.1 Union(慎重使用)

将第一个表的查询结果(不加limit,默认200条)跟第二个表的查询结果组合在一起,发送给客户端。

例子:

SELECT CityName FROM mrp_userlabel limit 1

union all

SELECT CityCode as CityName FROM mrp_userlabel limit 1

注:不建议,和分两次取结果一样,但效率会更慢。

3.4.2 Minus

3.4.2.1 基本实现

将第一个查询结果作为一个集合(已删除重复项),然后运行第二个查询,检查第二个查询的每条数据是否已经存在于第一个查询结果集中,若存在,则从集合中移除。最后返回集合。

例子:

一个字段:移除成都市的记录:

SELECT  CityName FROM mrp_userlabel WHERE CityName in ('成都市','重庆市') limit 10

minus

SELECT  CityName FROM mrp_userlabel WHERE CityName in ('成都市') limit 10

2个字段(对比一整条记录):还是会查出成都市的记录:

SELECT  CityName, CityCode FROM mrp_userlabel WHERE CityName in ('成都市','重庆市') limit 10

minus

SELECT  CityName, CityName as CityCode FROM mrp_userlabel WHERE CityName in ('成都市') limit 10

3.4.2.2 scrolling 滚动

当第二个查询数据量很大时,可使用scrolling 以提高性能。此时需要添加如下注释:

/*! MINUS_SCROLL_FETCH_AND_RESULT_LIMITS(maxFetchOnFirstTable,maxFetchOnSecondTable,docsFetchFromShardOnEachScroll) */

例子:

SELECT /*! MINUS_SCROLL_FETCH_AND_RESULT_LIMITS(100000,10000000,5000) */ 

 CityName, CityCode FROM mrp_userlabel WHERE CityName in ('成都市','重庆市') limit 1000

minus

SELECT  CityName, CityName as CityCode FROM mrp_userlabel WHERE CityName in ('成都市') limit 1000

3.4.2.3 Scrolling and Terms 优化

当只Minus一个字段的时候,有效。当两个查询数据量都很大的时候,可使用此优化以保证较低的负载。需要添加如下注释:

/*! MINUS_SCROLL_FETCH_AND_RESULT_LIMITS(maxFetchOnFirstTable,maxFetchOnSecondTable,docsFetchFromShardOnEachScroll) */

/*! MINUS_USE_TERMS_OPTIMIZATION(true)*/

例子:

SELECT /*! MINUS_SCROLL_FETCH_AND_RESULT_LIMITS(100000,10000000,5000) */ 

/*! MINUS_USE_TERMS_OPTIMIZATION(true)*/

 CityName FROM mrp_userlabel WHERE CityName in ('成都市','重庆市') limit 5000

minus

SELECT  CityName FROM mrp_userlabel WHERE CityName in ('成都市') limit 5000

四、扩展ES功能

增加了一些ES特有的扩展功能:

  1. ES MISSING
  2. ES STATS
  3. ES EXTENDED_STATS
  4. ES PERCENTILES
  5. ES TERMS/TERM
  6. ES IDS syntax: IDS_QUERY(type, ids..)
  7. ES QUERY_STRING

1)查找mrp_userlabel中,字段CustName(不)为空的数据:

SELECT * FROM mrp_userlabel where CustName is not missing

SELECT * FROM mrp_userlabel where CustName is missing

--以上is missing相当于is null

 

2)某字段in一组值内时,in后面只能跟1024个值,超过会报错,可用IN_TERMS[l4] 代替:

查找mrp_userlabel中,字段CityName(不)属于成都市或合肥市或重庆市的数据:

SELECT * FROM mrp_userlabel where CityName = IN_TERMS('成都市','合肥市','重庆市')

SELECT * FROM mrp_userlabel where not CityName = IN_TERMS('成都市','合肥市','重庆市')

 

3)查找mrp_userlabel中,字段CityName等于成都市的数据:

SELECT * FROM mrp_userlabel where CityName = TERM('成都市')

SELECT * FROM mrp_userlabel where not CityName = TERM('成都市')

 

4)查找mrp_userlabel中,主键_id等于**的数据:

SELECT * FROM mrp_userlabel where _id = IDS_QUERY(mrp_userlabel, '66f5c013-1f10-4557-b473-e22ba7b2cc6d_20181022','2e171f39-6ea1-40b1-8494-b0141fcbcbb2_20181022')

 

5)查找mrp_userlabel中,字段MarketName等于*的数据:

SELECT * FROM mrp_userlabel where q = query('MarketName:济南特来电新能源有限公司')

 

6)查找mrp_userlabel中,字段CustCode匹配正则表达式CD008.*的数据:

SELECT * FROM mrp_userlabel where CustCode = REGEXP_QUERY('CD008.*', 'INTERSECTION|COMPLEMENT|EMPTY', 10000)

五、注意事项

  1. 查询语句末尾如果不加limit,则默认返回200条数据。Limit最大值为10000,经过特殊设置的索引除外;
  2. 聚合时,不支持字段加减运算后聚合以及聚合后加减运算:

sum(CharMoneySC+CharMoneyEC)以及sum(CharMoneySC)+sum(CharMoneyEC)。可使用script脚本实现:

select sum(script('aa','return doc["尖时电量"].value + doc["平时电量"].value;')) as Total from etlchargebills

where BillSrc='SD' and 充电日期>='20160101+08:00' and 充电日期<'20190201+08:00'

group by 充电日期 order by 充电日期 limit 100

  1. 普通排序:

1)order by默认方式为asc升序,如果order by多个字段,且每个字段都为desc排序,需要每个字段后面都加上desc;

2)有limit限制的,limit必须放在order by后面才能排序正确:

SELECT CharPower,CharMoney

FROM mrp_userlabel

order by CharPower desc, CharMoney desc

limit 10

以上sql先按照“CharPower” 降序排列,“CharPower”值相同的,再按照“CharMoney”降序排列。

  1. 聚合排序:

1)group by一个字段,order by多个字段:只能按照最后一个字段排序:

 

2)同样的group by一个字段,order by后面跟一个维度+一个值的时候,排序只按照最后一个字段排序:

 

3)group by两个字段时,由于ES聚合的分桶机制,导致排序不正确:

 

解决方案:可在ES索引中增加一个字段AA,值=CityCode+CityName,然后按照AA分组排序即可解决。

  1. 查询时,注意将两侧集群切换一致,否则查询出错:

 

6. 关于TopHits:

Sql虽然支持topHits写法,但是topHits不起作用,实际返回结果并没有具体值:

SELECT topHits('size'=2,floatValue='desc') FROM test_wj group by name limit 10;

 

原因在于elasticsearch-sql源码中没有解析聚合后的TopHits结果集:

 

但是可通过DSL查询获取相关TopHits的结果集:

 

六、附录:

6.1 Script基本用法:

有时简单的ES Sql语句无法支持某些查询(如【二、快速入门】--【字段之间的运算1/2】),此时需要在sql语句中使用script语句。

前面已经说过,Elasticsearch的查询语言是DSL,由于比较复杂,因此第三方开发了插件Elasticsearch-SQL。因此要介绍script在ES Sql中的用法,必须先了解script在DSL中的用法。语法如下:

"script": {

    "lang":   "painless", 

    "source" | "id": "...",

    "params": { ... }

  }

脚本参数说明:

l  lang:指定编写脚本的语言,默认为painless。

l  source,id:指定脚本的来源,inline脚本是指定source,如上例所示,存储的脚本是指定的id,并从群集状态中检索(请参阅存储的脚本)。

l  params:指定作为变量传递到脚本的任何命名参数。

painless是一种简单,安全的脚本语言,专为与Elasticsearch一起使用而设计,它是Elasticsearch的默认脚本语言,可以安全地用于内联和存储脚本,有关painless语法和语言功能的详细说明,请参阅:https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting-painless.html

以下主要分为Script Fields、Script Query来介绍:

6.1.1 Script Fields(查询字段):

参考:

https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-script-fields.html

  1. GET test_wj/_search  
  2.     "from": 0, 
  3.     "size": 10, 
  4.     "_source": { 
  5.         "includes": [], 
  6.         "excludes": [] 
  7.     },  
  8.     "script_fields": { 
  9. 10.         "aa": { 
  10. 11.             "script": { 
  11. 12.                 "source": "doc[\"floatValue\"].value * 2", 
  12. 13.                 "lang": "painless" 
  13. 14.             },  
  14. 15.             "ignore_failure": false  
  15. 16.         }  
  16. 17.     }  

18. }  

以上语句中计算字段floatValue*2的值,返回新字段aa。并使用doc关键字获取字段值。Doc Values介绍如下:

在 Elasticsearch中,Doc Values就是一种列式存储结构,默认情况下每个字段的Doc Values都是激活的,Doc Values是在索引时创建的,当字段索引时,Elasticsearch 为了能够快速检索,会把字段的值加入倒排索引中,同时它也会存储该字段的“Doc Values”。

Elasticsearch 中的Doc Values常被应用到以下场景:

l  对一个字段进行排序;

l  对一个字段进行聚合;

l  某些过滤,比如地理位置过滤;

l  某些与字段相关的脚本计算。

6.1.2 Script Query(过滤条件):

参考:

https://www.elastic.co/guide/en/elasticsearch/reference/6.0/query-dsl-script-query.html

query过滤查询可以使用script,并且用在filter context中:

  1. GET test_wj/_search  
  2.     "from": 0, 
  3.     "size": 10, 
  4.     "query": { 
  5.       "bool": { 
  6.         "must":{ 
  7.           "script": { 
  8.             "script": { 
  9. 10.               "source": "doc[\"floatValue\"].value > 2 && doc[\"doubleValue\"].value > doc[\"floatValue\"].value", 
  10. 11.               "lang": "painless" 
  11. 12.               }  
  12. 13.            }  
  13. 14.          }  
  14. 15.         }  
  15. 16.     }  

17. }  

以上语句查询字段floatValue值大于2且doubleValue值大于floatValue值的数据。

6.1.3 Script 在 ES Sql中的用法:

Script在ES Sql中的用法也分为Script Fields、Script Query来介绍。

1、Script Field(查询字段):

select script('aa','doc["floatValue"].value * 2') as aa1 from test_wj limit 10

可把script看为带2个参数的函数,其中第一个参数'aa'相当于script_fields名称,第二个参数相当于DSL语句中的script的source。以上sql相当于【6.1.1 Script Fields(查询字段)】中的DSL语句。具体如下:

 

2、Script Query(过滤条件):

select * from test_wj where script('doc["floatValue"].value > 2 && doc["doubleValue"].value > doc["floatValue"].value') limit 10

可把script看为带1个参数的函数,其中参数相当于DSL语句中的script的source。以上sql相当于【6.1.2 Script Query(过滤条件)】中的DSL语句。具体如下:

 

其他例子:

SELECT PhotoTime, script('ConvertedUptime','painless','def date_format_1606432247 = new SimpleDateFormat(\'yyyyMMdd\').format(new Date(doc[\'PhotoTime\'].value + 8*1000*60*60));return date_format_1606432247;')  from vehiclephotopath_201812 limit 10

--注意,"script"的"source",有def定义字段或者函数时,必须有return返回值

 

SELECT sum(script('aa','return doc["floatValue"].value * 2;')) as aa1 from test_wj limit 10

--script也可用于sum等聚合统计

 

SELECT IndustryType,City, SumPower

from JZDS_StationRPT

WHERE script('def cc = ["北京市","青岛市"];doc["IndustryType"].value != "公交" &&  cc.contains(doc["City"].value)')  and SumPower > 50

limit 100

 

 

select PileCanSN, cast(PileCanSN AS INT) as b

from  chargebillwidetable

where PileCanSN  <> '' and script('return Integer.parseInt(doc["PileCanSN"].value.toString()) > 180')

limit 10

--cast函数不能用在where条件后面,只能用在select后面

七、待办:

1、聚合查询,group by多字段后,必须用terms,此时无法支持分页以及排序:

SELECT 电站名称,  电站编号,电站ID,

sum(充电量) 充电电量,sum(订单数) 充电次数      

FROM etldaystasum      

where 1=1 AND 业务日期='20190304+08:00'        

group by terms(field='电站名称',size='10000',alias='电站名称'),terms(field='电站编号',size='10000',alias='电站编号'),terms(field='StaID',size='10000',alias='电站ID')

Order by  充电电量 desc  

limit 10,20

以上sql中,limit from size方式分页不起作用;order by排序也不起作用。

2、ES max聚合只能针对数值型字段,不能对string类似进行max聚合。

 


 [l1]在Elasticsearch查询结果集中,默认按照相关性进行排序,相关性越高,排名越靠前。相关性分值会用_score字段来给出一个浮点型的数值,所以默认情况下,结果集以_score进行倒序排列。

 [l2]IN_TERMS只用于keyword类型字段。

IN_TERMS也有上限,默认65536,可以修改索引级别参数index.max_terms_count设置。此参数设置过大查询会很慢而且会影响集群性能。

https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-terms-query.html

 [l3]目前验证只支持*通配符,不支持?、[]、{}等其他通配符

 [l4]IN_TERMS只用于keyword类型字段。

IN_TERMS也有上限,默认65536,可以修改索引级别参数index.max_terms_count设置。此参数设置过大查询会很慢而且会影响集群性能。

https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-terms-query.html

转载于:https://www.cnblogs.com/wlzhang/p/11039312.html

你可能感兴趣的:(ES SQL使用说明文档)