zoukankan      html  css  js  c++  java
  • es 按照日期字段,统计每天总数

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

    可用间隔如下:

    1y

    INTERVAL 1 YEAR

    2M

    INTERVAL 2 MONTH

    3w

    INTERVAL 21 DAY

    4d

    INTERVAL 4 DAY

    5h

    INTERVAL 5 HOUR

    6m

    INTERVAL 6 MINUTE

    7s

    INTERVAL 7 SECOND

    以下转自:https://www.cnblogs.com/wlzhang/p/11039312.html

    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特有的扩展功能:

    ES MISSING
    ES STATS
    ES EXTENDED_STATS
    ES PERCENTILES
    ES TERMS/TERM
    ES IDS syntax: IDS_QUERY(type, ids..)
    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)

    五、注意事项
    查询语句末尾如果不加limit,则默认返回200条数据。Limit最大值为10000,经过特殊设置的索引除外;
    聚合时,不支持字段加减运算后聚合以及聚合后加减运算:
    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)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)group by一个字段,order by多个字段:只能按照最后一个字段排序:

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

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

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

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

    1. 关于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

    GET test_wj/_search  

        "from": 0, 
        "size": 10, 
        "_source": { 
            "includes": [], 
            "excludes": [] 
        },  
        "script_fields": { 
    10.         "aa": { 
    11.             "script": { 
    12.                 "source": "doc["floatValue"].value * 2", 
    13.                 "lang": "painless" 
    14.             },  
    15.             "ignore_failure": false  
    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中:

    GET test_wj/_search  

        "from": 0, 
        "size": 10, 
        "query": { 
          "bool": { 
            "must":{ 
              "script": { 
                "script": { 
    10.               "source": "doc["floatValue"].value > 2 && doc["doubleValue"].value > doc["floatValue"].value", 
    11.               "lang": "painless" 
    12.               }  
    13.            }  
    14.          }  
    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 + 8100060*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设置。此参数设置过大查询会很慢而且会影响集群性能
    ————————————————
    版权声明:本文为CSDN博主「zwhfyy」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/zwhfyy/java/article/details/100155564

  • 相关阅读:
    docker 构建带健康检查的redis镜像
    HP服务器 开启ILO
    [转]如何取得当前正在执行的shell脚本的绝对路径?
    解决方案:centos运行shell脚本时报“$' ': 未找到命令”
    Js控制滚动条
    json_decode时含有中文是解码问题(json_decode返回为null)
    Phaser开源2d引擎 html5游戏框架中文简介
    js 开启video全屏模式
    修改mysql用户名密码 和 PHPmysqlAdmin对应密码修改
    用javascript判断一个html元素是否存在的五种方法:
  • 原文地址:https://www.cnblogs.com/ellafive/p/12794203.html
Copyright © 2011-2022 走看看