1.Elasticsearch是数据库,不是普通的Java应用程序,传统数据库需要的硬件资源同样需要,提升性能最有效的就是升级硬件。
2.Elasticsearch是文档型数据库,不是关系型数据库,不具备严格的ACID事务特性,任何企图直接替代严格事务性场景的应用项目都会失败!!!
3.Elasticsearch原则上适合一切非事务性应用场景或能够容许一定的延迟的事务性场景;能最大限度的替代mongodb与传统关系型数据库
索引字段与属性都属于静态设置,若后期变更历史数据需要重建索引才可生效
对历史数据无效!!!!
一定要重建索引!!!!
1、Script概要介绍
Script概念
概念解释
ES的脚本类同传统数据库的UDF,可以自定义一些规则表达式,目的是满足日益复杂的应用需求
Greenplum,支持Python/R
应用便利
支持灵活多变的应用场景与需求如:字段数值乘以10倍数
参数
script,定义脚本查询入口
lang,定义脚本语言
source,定义脚本内容
id,脚本编号名称,预定义脚本
params,定义脚本参数,全局参数
# eg 乘以10
GET kibana_sample_data_flights/_search
{
"query":{
"match_all": {}
},
"script_fields":{
"AvgTicketPrice_100":{
"script":{
"lang": "expression",
"source": "doc['AvgTicketPrice']*10"
}
}
}
}
Script脚本类型
脚本类型
1.Painless,最丰富的强大的脚本语言
2.Lucene,简洁高效的原生lucene脚本语言
3.Mustache,简洁高效的template脚本语言
4.Java,原生支持iava高级自定义的脚本语言
Script获取上下文数据值
获取上下文数据值
1.update script,数据更新上下文获取数据
2._score,数据分值
3.doc_value,从列式获取数据值
4._source,从原数据中获取数据值
5._store,从lucene存储中获取数据值
# update script,eg 从Script获取数据,更新字段值
GET kibana_sample_data_flights_3share/_search
POST kibana_sample_data_flights_3share/_update_by_query
{
"script":{
"source": """
ctx._source.FlightNum=ctx._source.OriginCountry + "_"+ctx._source.FlightNum
"""
}
}
GET kibana_sample_data_flights_3share/_search
# _score,eg 从Script获取数据,修改分值
GET kibana_sample_data_flights_3share/_search
{
"query": {
"function_score": {
"query": {
"match": {
"Origin": "Newark"
}
},
"script_score": {
"script": {
"lang": "expression",
"source": "_score*doc['FlightTimeMin']"
}
}
}
}
}
# doc_value,eg 从Script获取数据,修改分值
GET kibana_sample_data_flights_3share/_search
{
"query": {
"function_score": {
"query": {
"match": {
"Origin": "Newark"
}
},
"script_score": {
"script": {
"lang": "expression",
"source": "doc['FlightTimeMin']*10"
}
}
}
}
}
# _source,eg 从Script获取数据,更新字段值
GET kibana_sample_data_flights_3share/_search
POST kibana_sample_data_flights_3share/_search
{
"script_fields": {
"FlightNum": {
"script": {
"lang": "painless",
"source": "params._source.FlightNum+'_'+ params._source.OriginCityName"
}
}
}
}
# _store, eg 从lucene-store中获取数据
# 创建索引时需要设定store=true,否则出错
PUT dev-001
{
"mappings":{
"properties":{
"devName":{
"type":"text",
"store":true
},
"devDesc":{
"type":"text",
"store":true
}
}
}
}
POST dev-001/_doc
{
"devName":"设备名称-1",
"devDesc":"设备描述内容"
}
GET dev-001/_search
{
"stored_fields":["*"],
"script_fields":{
"devInfo":{
"script":{
"lang": "painless",
"source": "params._fields['devName'].value+'_'+params._fields['devDesc'].value"
}
}
}
}
脚本接口(扩展了解)
script_context
查询脚本执行支持的上下文参考
GET _script_context
_script_language
查询内置已经注册脚本语言类型
内置脚本语言支持的上下文
GET _script_language
scripts 创建
创建内置脚本,便于编译,提升执行能力
*PUT _scripts/<script-id>
*POST _scripts/<script-id>
*PUT _scripts/<script-id>/<context>
*POST _scripts/<script-id>/<context>
2、Lucene脚本应用
Lucene概要介绍
1.继承Lucene原生,简洁高效,表达能力有限
2.官方名称:expression
其它能力
1.性能最好
expression, eg
Lucene,继承原生lucene内置能力,性能好,简洁直接,性能同比其它,最好
查询参数
lang,定义查询语言类型
expression,lucene 语言类型
doc,获取参数
# 获取日期的一天中的小时
GET kibana_sample_data_flights/_search
{
"_source": [
"timestamp"
],
"track_total_hits": true,
"script_fields": {
"hourOfDay": {
"script": {
"lang": "expression",
"source": "doc['timestamp'].date.hourOfDay"
}
}
}
}
## 限制性条件
# 仅能获取数值、日期、geo_point类型
3、Mustache脚本应用
基于 Mustache 模板语法规则,简单适用
查询模板
GET _search/template
{
"source": {
"query": {
"match": {
"{{my_field}}": "{{my_value}}"
}
},
"size": "{{my_size}}"
},
"params": {
"my_field": "message",
"my_value":"foo",
"my_size":10
}
}
4、Painless脚本应用深入探查
概要介绍
1.基于自定义脚本规则,语言语法参考python/java,简洁高效,语言能力丰富。
2.Painless是编译模型,基于ANTLR4与ASM库编译
3.内置沙箱机制,非常安全
https://github.com/antlr/antlr4
https://zhuanlan.zhihu.com/p/575048391
查询参数
lang,定义查询语言类型
painless,查询语言
source,查询语言表达式
# eg
GET kibana_sample_data_flights/_search
{
"query":{
"match_all": {}
},
"script_fields":{
"AvgTicketPrice_100":{
"script":{
"lang": "expression",
"source": "doc['AvgTicketPrice']*10"
}
}
}
}
scripts/painless/_execute 测试接口
查询参数
POST /scripts/painless/execute
script,脚本表达式定义
context,上下文逻辑表达式
context_setup,上文参数,指定索引与字段替代等
test-context
默认测试上下文
测试自定义变量
# eg 1
POST /_scripts/painless/_execute
{
"script": {
"source":"params.count/params.total",
"params": {
"count":11.0,
"total":1100.0
}
}
}
# eg 2
POST /_scripts/painless/_execute
{
"script": {
"source":"""
int i=10;
float f=(float)i;
float i_f=i*f;
return i_f*params.p1;
""",
"params": {
"p1": 100,
"p2": 1000
}
}
}
filter-context
过滤上下文,查询逻辑表达式
bool 表达式
# eg
POST /_scripts/painless/_execute
{
"script": {
"source":"""
int i=10;
float f=(float)i;
float i_f=i*f;
float f1= i_f*params.p1;
return f1<doc['AvgTicketPrice'].value;
""",
"params": {
"p1": 100,
"p2": 1000
}
},
"context":"filter",
"context_setup":{
"index":"kibana_sample_data_flights",
"document":{
"AvgTicketPrice":100.11
}
}
}
score-context
数值上下文
# eg
POST /_scripts/painless/_execute
{
"script": {
"source":"""
int i=10;
float f=(float)i;
float i_f=i*f;
float f1= i_f*params.p1;
return f1+doc['AvgTicketPrice'].value;
""",
"params": {
"p1": 100,
"p2": 1000
}
},
"context":"score",
"context_setup":{
"index":"kibana_sample_data_flights",
"document":{
"AvgTicketPrice":100.11
}
}
}
限制性条件
性能限制
脚本语言越复杂,性能原则上越差
权限限制
脚本执行是在沙箱中进行,不能超过java 或者 es 权限限制边界,如禁止访问 IO 等
5、Java脚本应用自定义能力探查
当以上3种脚本无法满足特定诉求,可以基于java 语言自定义构造特殊的脚本,如需要突破IO 访问限制
或者与其它框架集成等
eg
1、编写java插件 ExpertScriptPlugin.java
参考官方案例
https://www.elastic.co/guide/en/elasticsearch/reference/8.6/modules-scripting-engine.html
2、编译运行包
基于 gradle 构件程序包
jar包位置:elasticsearch-8.6.2\plugins\examples\script-expert-scoring\build\distrlbutions
3、复制到 Plugins 目录
例如我的目录是D:\Software\elasticsearch-8.6.2
进该目录下的plugins文件夹,这个文件夹默认是空的,在plugins下创建一个插件目录
将自己的jar复制进来
4、新增配置文件
新增配置文件plugin-descriptor.properties
#(可以在elasticsearch-8.6.2\modules\x-pack-async目录下拷一份过来改改)
重启es,通过_script_language查看支持的脚本,比原先多一个
GET _script_language