ES SQL使用說明文檔

ES SQL使用說明文檔html

1、Elasticsearch術語介紹

l  接近實時(NRT):node

Elasticsearch 是一個接近實時的搜索平臺。這意味着,從索引一個文檔直到這個文檔可以被搜索到有一個很小的延遲,包括若是作了集羣的話,集羣中的各個節點數據同步也是接近實時的。正則表達式

l  集羣(cluster):sql

一組擁有共同的 cluster name 的節點。數據庫

l  節點(node):安全

集羣中的一個 Elasticearch 實例。app

l  索引(index):less

ElasticSearch將它的數據存儲在一個或多個索引(index)中。用SQL領域的術語來類比,索引就像數據庫,能夠向索引寫入文檔或者從索引中讀取文檔。elasticsearch

l  文檔類型(type):ide

文檔類型(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查詢時:

一、在hue中查詢時,select前不能有空格或者空行;

二、查詢中字段名大小寫敏感;

三、求個數時,不能用 count(1), 必須是count(*);

四、select 字段名,* from….時  後面的*不起做用;

五、目前支持中文字段查詢,但不支持帶特殊符號的字段做爲where條件,例如不支持where 總訂單數(條)>20;

六、兩個整數類型字段相除時,獲得的結果也是整數,此時至少一個字段須要化爲小數(例如乘除1.0、加減0.0):

SELECT 慢充終端數,快充終端數,1.0*慢充終端數/快充終端數 as a

from etlddcharging

where 快充終端數>0 and 慢充終端數>0 limit 10

2、快速入門:

ES查詢默認查詢200條,最大查詢10000條,可經過max_result_window修改。

一、查詢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 (錯誤)

二、使用別名:

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 ;

三、分頁查詢:

SELECT * from mrp_userlabel limit 10,20

其中limit後面第一個參數是from,表示目標數據的偏移值,第二個參數是size,表示數據條數。以上查詢第10到第30條數據[l1] 。可是ES最大查詢默認max_result_window =10000條,當 from + size > max_result_window 時,es 將返回錯誤。

四、計算列--能夠加減乘除固定數值,也能夠兩個字段之間進行加減乘除:

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

 

五、數字範圍過濾--大於等於小於運算:

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基本用法:】

六、查詢日期字段:

見【3.2 函數支持】,使用date_format函數,支持傳遞時區。

七、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')

八、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、基本用法

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.一、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

4、擴展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)

5、注意事項

  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、附錄:

6.1 Script基本用法:

有時簡單的ES Sql語句沒法支持某些查詢(如【2、快速入門】--【字段之間的運算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來介紹。

一、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語句。具體以下:

 

二、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後面

7、待辦:

一、聚合查詢,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排序也不起做用。

二、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

相關文章
相關標籤/搜索