• Elasticsearch学习--script


    一、概念

     es1.4-5.0,默认脚本语言是Grovvy

    es5.0+,默认脚本语言是painless

     二、简单使用

    将price减一

    1. # 将id=1的price减一
    2. POST goods/_update/1
    3. {
    4. "script": {
    5. "source": "ctx._source.price -= 1"
    6. }
    7. }
    8. # 简写
    9. POST goods/_update/1
    10. {
    11. "script": "ctx._source.price -= 1"
    12. }

    其中,ctx是一个上下文对象 ,用在对数据的修改上

    三、CRUD

    1、数据备份

    (数据来源可以查看:CSDN

    1. #将goods中的数据备份到goods2中
    2. POST _reindex
    3. {
    4. "source": {
    5. "index": "goods"
    6. },
    7. "dest": {
    8. "index": "goods2"
    9. }
    10. }

    2. 新增数组中的值

    1. # 将id=1的tags新增一个值
    2. POST goods/_update/1
    3. {
    4. "script": "ctx._source.tags.add('无线充电')"
    5. }

    3. 根据id删除

    1. # 删除id=11的数据
    2. POST goods/_update/11
    3. {
    4. "script": "ctx.op='delete'"
    5. }

     4. upsert

    如果数据存在执行script中的updated,如果数据不存在,执行upsert中created

    1. POST goods/_update/15
    2. {
    3. "script": {
    4. "source": "ctx._source.price += 100"
    5. },
    6. "upsert": {
    7. "name":"香蕉",
    8. "price": 599
    9. }
    10. }

    第一次执行结果

     第二次执行结果

     5. 查询

    使用expression和painless两种语言进行查询,查询结果相同

    1. GET goods/_search
    2. {
    3. "script_fields": {
    4. "new_price": {
    5. "script": {
    6. "lang": "expression",
    7. "source": "doc['price'].value * 0.9"
    8. }
    9. }
    10. }
    11. }
    12. GET goods/_search
    13. {
    14. "script_fields": {
    15. "new_price": {
    16. "script": {
    17. "lang": "painless",
    18. "source": "doc['price'] * 0.9"
    19. }
    20. }
    21. }
    22. }

    painless,doc['age'].value和doc['age']都能正确输出,但是doc['age'] * 0.9报错
    expression,doc['age'].value和doc['age']都能正确输出,doc['age'] * 0.9和doc['age'].value * 0.9也都不报错

    但是,painless,如果字段为空,*0.9会报错

    expression:只能访问数字、布尔值、日期等,存储的字段不可用

    es源数据是map类型的,在取值的时候,要根据doc['x xx']取值

    update用ctx,查询的时候用doc

    6. 参数化查询

    给interest加一个值aaa

    1. POST indexname/_update/2
    2. {
    3. "script": {
    4. "lang": "painless",
    5. "source": "ctx._source.interest.add('aaa')"
    6. }
    7. }

    es在首次执行脚本的时候,会对执行的脚本进行编译,并且把编译的结果放在缓冲区内。es的缓冲区默认只有100M,编译操作很消耗性能,es每分钟支持的编译次数是15次
    解决方案是:

    1. POST indexname/_update/2
    2. {
    3. "script": {
    4. "lang": "painless",
    5. "source": "ctx._source.interest.add(params.inserest_name)",
    6. "params": {
    7. "inserest_name":"bbb"
    8. }
    9. }
    10. }

    这样,参数是动态传递的,没有硬编码,下次参数内容发生改变,但是脚本没有发生改变,不需要重新编译,节省性能

    同理,也可以这样                                                                                                      

    1. GET indexname/_search
    2. {
    3. "script_fields": {
    4. "new_age": {
    5. "script": {
    6. "lang": "painless",
    7. "source":"doc['age'].value * params.num",
    8. "params": {
    9. "num": 0.9
    10. }
    11. }
    12. }
    13. }
    14. }

    如果是expression,就要把params.num改成num

    1. GET indexname/_search
    2. {
    3. "script_fields": {
    4. "new_age": {
    5. "script": {
    6. "lang": "expression",
    7. "source":"doc['age'].value * num",
    8. "params": {
    9. "num": 0.9
    10. }
    11. }
    12. }
    13. }
    14. }

    结果数组

    1. GET indexname/_search
    2. {
    3. "script_fields": {
    4. "age": {
    5. "script": {
    6. "lang": "painless",
    7. "source":"doc['age'].value"
    8. }
    9. },
    10. "new_age": {
    11. "script": {
    12. "lang": "painless",
    13. "source":"[doc['age'].value - params.num_1,doc['age'].value - params.num_2,doc['age'].value - params.num_3]",
    14. "params": {
    15. "num_1": 1,
    16. "num_2": 2,
    17. "num_3": 3
    18. }
    19. }
    20. }
    21. }
    22. }

    四、stored scripts:scripts模板

    1. 操作脚本

    因为脚本编译比较消耗性能,可以把脚本保存在集群的缓存中

    语法

    /_scripts/{script_id}

    创建脚本

    1. POST _scripts/age_num
    2. {
    3. "script":{
    4. "lang": "painless",
    5. "source":"doc['age'].value - params.num"
    6. }
    7. }

    查看脚本

    GET _scripts/age_num

    使用脚本

    1. GET indexname/_search
    2. {
    3. "script_fields": {
    4. "age": {
    5. "script": {
    6. "lang": "painless",
    7. "source":"doc['age'].value"
    8. }
    9. },
    10. "new_age": {
    11. "script": {
    12. "id": "age_num",
    13. "params": {
    14. "num": 0.9
    15. }
    16. }
    17. }
    18. }
    19. }

    2. scripting的函数式编程

    在source中加""",三个双引号

    1. POST indexname/_update/2
    2. {
    3. "script": {
    4. "lang": "painless",
    5. "source": """
    6. ctx._source.interest.add(params.inserest_name);
    7. ctx._source.age-=1;
    8. """,
    9. "params": {
    10. "inserest_name": "bbb"
    11. }
    12. }
    13. }

    如果name中包含aa:name+bb;否则,不操作。==~是匹配的意思

    1. POST indexname/_update/2
    2. {
    3. "script": {
    4. "lang": "painless",
    5. "source": """
    6. if(ctx._source.name ==~ /[\s\S]*aa[\s\S]*/){
    7. ctx._source.name+="bb"
    8. }else{
    9. ctx.op="noop"
    10. }
    11. """
    12. }
    13. }

    for循环取insterst的总数

    1. GET indexname/_search
    2. {
    3. "aggs": {
    4. "agg_insterst": {
    5. "sum": {
    6. "script": {
    7. "lang": "painless",
    8. "source": """
    9. int total=0;
    10. for(int i=0; i
    11. total++;
    12. }
    13. return total;
    14. """
    15. }
    16. }
    17. }
    18. }
    19. }

    doc['filed']:会被加载到内存中,效率更高,更消耗内存,只允许简单类型,object和nested属于复杂类型。推荐
    params['_source']['field']:每次都要重新加载,重新解析,可以用于复杂类型
     

  • 相关阅读:
    Java快问快答
    高清图片、视频素材免费下载
    RBTree(红黑树)模拟实现(插入)
    如何在.NET程序崩溃时自动创建Dump?
    go mod 使用三方包、go get命令
    LabVIEW示波器连续触发编程
    Docker容器数据卷入门教程(超详细)
    导师问我打开句柄fd和没有打开的差异在哪里?
    屏幕显示技术进化史
    使用Mybatis框架操作数据,在Springboot框架集成Mybatis
  • 原文地址:https://blog.csdn.net/CelineT/article/details/126713188