何小豆儿在此 发表于 2024-12-25 22:54:38

Elasticsearch-脚本查询

脚本查询


[*] 概念

Scripting是Elasticsearch支持的一种专门用于复杂场景下支持自定义编程的强盛的脚本功能,ES支持多种脚本语言,如painless,其语法类似于Java,也有注释、关键字、类型、变量、函数等,其就要相对于其他脚本高出几倍的性能,并且安全可靠,可以用于内联和存储脚本。
[*] 支持的语言
[*] groovy:ES 1.4.x-5.0的默认脚本语言
[*] painless:JavaEE利用java语言开发,.Net利用C#/F#语言开发,Flutter利用Dart语言开发,同样,ES 5.0+版本后的Scripting利用的语言默认就是painless,painless是一种专门用于Elasticsearch的简单,用于内联和存储脚本,是ES 5.0+的默认脚本语言,类似于Java,也有注释、关键字、类型、变量、函数等,是一种安全的脚本语言。并且是Elasticsearch的默认脚本语言。
[*] 其他:
expression:每个文档的开销较低:表达式的作用更多,可以非常快速地实行,甚至比编写native脚本还要快,支持javascript语法的子集:单个表达式。缺点:只能访问数字,布尔值,日期和geo_point字段,存储的字段不可用
mustache:提供模板参数化查询

[*] 特点
[*]语法简单,学习成本低
[*]灵活度高,可编程能力强
[*]性能相较于其他脚本语言很高
[*]安全性好
[*]独立语言,虽然易学但仍需单独学习
[*]相较于DSL性能低
[*]不适用于复杂的业务场景

[*] 应用场景:各种复杂的应用场景,如自定义评分、自定义聚合查询等。
[*] 正则:

早先某些版本正则表达式默认环境下处于禁用模式,由于它绕过了painless的针对长时间运行和占用内存脚本的保护机制。而且有深度对战活动。如果需要开启正则,需要配置:script.painless.regex.enabled: true
注意:通常正则的利用范围比力小,应用范围基本限定在数据量比力小和并发量比力小的应用场景下。
[*] doc[‘field’].value和params[‘_source’][‘field’]:

理解之间的区别是很告急的,doc[‘field’].value和params[‘_source’][‘field’]。起首,利用doc关键字,将导致该字段的条件被加载到内存(缓存),这将导致更快的实行,但更多的内存斲丧。此外,doc[…]符号只答应简单类型(不能返回一个复杂类型(JSON对象或者nested类型)),只有在非分析或单个词条的底子上有意义。但是,doc如果可能,利用仍然是从文档访问值的推荐方式,由于_source每次利用时都必须加载并解析。利用_source非常痴钝
脚本查询-实战教程

1、对索引中的数据进行修改
价格减一
POST product/_update/2
{
"script": {
    "source": "ctx._source.price-=1"
}
}

小米10出了新款 新增了tag 叫做“无线充电”
POST product/_update/6
{
"script": {
    "lang": "painless",
    "source": "ctx._source.tags.add('无线充电')"
}
}
2、将文档从一个索引复制到另一个索引。它答应用户将数据从一个索引重新索引到另一个索引
POST _reindex
{
"source": {
    "index": "product"
},
"dest": {
    "index": "product2"
}
}
3、删除索引中的数据
实行delete操作
POST product/_update/10
{
"script": {
    "lang": "painless",
    "source": "ctx.op='delete'"
}
}
4、upsert有则更新否则插入
POST product/_update/19
{
"script": {
    "lang": "painless",
    "source": "ctx._source.price += 100"
},
"upsert": {
    "name" : "小米手机10",
    "desc" : "充电贼快掉电更快,超级无敌望远镜,高刷电竞屏",
    "price" : 1999
}
}
5、参数化操作索引数据
POST product/_update/6
{
"script": {
    "lang": "painless",
    "source": "ctx._source.tags.add(params.tag_name)",
    "params": {
      "tag_name":"无线秒充"
    }
}
}
6、对索引数据进行多次操作
GET product/_search
{
"script_fields": {
    "price": {
      "script": {
      "lang": "painless",
      "source": "doc['price'].value"
      }
    },
    "discount_price": {
      "script": {
      "lang": "painless",
      "source": ".value* params.discount_8,doc['price'].value* params.discount_7,doc['price'].value* params.discount_6,doc['price'].value* params.discount_5]",
      "params": {
          "discount_8": 0.8,
          "discount_7": 0.7,
          "discount_6": 0.6,
          "discount_5": 0.5
      }
      }
    }
}
}
7、模板脚本
#创建脚本模板
POST _scripts/calculate_discount
{
"script": {
    "lang": "painless",
    "source": "doc.price.value * params.discount"
}
}
#查看
GET _scripts/calculate_discount
#使用模板进行数据运算
GET product/_search
{
"script_fields": {
    "price": {
      "script": {
      "lang": "painless",
      "source": "doc['price'].value"
      }
    },
    "discount_fields": {
      "script": {
      "id": "calculate_discount",
      "params": {
          "discount":0.8
      }
      }
    }
}
}
8、函数式编程
#Scripting的函数式编程
GET product/_search
GET product/_doc/1
POST product/_update/1
{
"script": {
    "lang": "painless",
    "source": "ctx._source.tags.add(params.tag_name)",
    "params": {
      "tag_name":"无线秒充"
    }
}
}

POST product/_update/1
{
"script": {
    "lang": "painless",
    "source": """
      ctx._source.tags.add(params.tag_name);
      ctx._source.price-=100;
    """,
    "params": {
      "tag_name":"无线秒充1"
    }
}
}
9、正则表达式
#正则like %小米% /[\s\S]*小米[\s\S]*/
POST product/_update/4
{
"script": {
    "lang": "painless",
    "source": """
      if(ctx._source.name ==~ /[\s\S]*小米[\s\S]*/) {
      ctx._source.name+="***|"
      }else{
      ctx.op="noop"
      }
    """
}
}
#/\d{4}-\d{2}-\d{2}[\s\S]*/
GET product/_doc/1
POST product/_update/1
{
"script": {
    "lang": "painless",
    "source": """
      if(ctx._source.createtime ==~ /\d{4}-\d{2}-\d{2}[\s\S]*/) {
      ctx._source.name+="|***"
      }else{
      ctx.op="noop"
      }
    """
}
}
10、聚合查询一起利用
GET product/_search
#统计所有价格小于1000的商品的tag的数量 不考虑重复的情况
GET product/_mapping
GET product/_search
{
"query": {
    "constant_score": {
      "filter": {
      "range": {
          "price": {
            "lte": 1000
          }
      }
      }
    }
},
"aggs": {
    "tag_agg": {
      "sum": {
      "script": {
          "lang": "painless",
          "source": """
            int total = 0;
            for(int i = 0; i <doc['tags.keyword'].length; i++){
            total++;
            }
            return total;
          """
      }
      }
    }
}
}

https://i-blog.csdnimg.cn/direct/10621e41bc074149aa5d483416c1b1a6.png

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: Elasticsearch-脚本查询