Elasticsearch执行sql脚本

357 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情

项目中有时候需要在ES里面聚合查询一些复杂数据,ES操作组件elasticsearch-rest-high-level-client能支持简单的聚合查询,涉及到复杂的聚合有些力不从心,那么我们可以直接在ES执行sql脚本呢? 这样是不是方便很多,以下代码可以帮助实现。

POST /_sql?format=txt
{
  "query": """select substring (cast(cast(cast(starttime as long) as date)as text),1,7) as cc , count(0) from workflow_order group by cc """
}

是不是很方便呢?项目中我们会把MYSQL的数据同步到ES,例如我们有一个复杂sql,需要在控制台执行,是不是需要爸复杂sql转换成DSL,是不是觉得很受伤,ES的DSL语句对于不太熟悉kibana开发者不是很友好,那么我们有什么方法方便快速写出一个复杂的DSL查询语句呢,ES当前提供了translate方法,如下:

POST /_sql/translate
{
  "query": """select substring (cast(cast(cast(startTime as long) as date)as text),1,7) , count(0) from workflow_order group by substring (cast(cast(cast(startTime as long) as date)as text),1,7)"""

}

执行后直接获取,是不是很方便呢(转换结果我就不粘贴,感兴趣的朋友自己试试)

实际开发中我们更多的需要在java代码中查询,那么如何处理呢?

直接粘代码

        HttpHost host = new HttpHost("10.0.88.99", 9200, HttpHost.DEFAULT_SCHEME_NAME);
        RestClientBuilder builder = RestClient.builder(host);
        CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("elastic", "123456"));
        builder.setHttpClientConfigCallback(f -> f.setDefaultCredentialsProvider(credentialsProvider));
        RestHighLevelClient client = new RestHighLevelClient(builder);


        Request request = new Request("POST", "/_sql");
        request.setJsonEntity("{\"query\":\"select count(1),code, FROM workflow_order where code is not null and   dataSource ='xx'  and projectCode  = 'xx' AND code IN('1','7','17') group by taskStatusCode\"}");
        try {
            Response response = client.getLowLevelClient().performRequest(request);
            String responseBody = EntityUtils.toString(response.getEntity(), "utf-8");
            System.out.println(responseBody);
        } catch (Exception e) {

        }

这样就不用消耗脑细胞,琢磨Es的查询条件如果封装,聚合条件如何装配,是不是很nice。

还有两个小知识点分享一下: 1、假如需要手动更新索引中的某个数据,同步生产,如何操作?

更新某个字段数据内容
POST _update_by_query
{
    "query": {
        "match": {
            "status": "UP_SHELF"
        }
    },
    "script": {
        "inline": "ctx._source['status'] = 'demo'"
    }
}

2、假如我们的索引结构做出修改,总不能删除之前的冲洗建一个同名字的索引,那么生产的千万数据就没了,是不是该考虑跑路了?

别慌,方法总是有的。 第一步:创建一个新的正确的索引sysconfig2(索引为sysconfig,修改原索引name字段为alias)

PUT /sysconfig2
{
  "mappings": {
    "properties": {
      "alias":{
        "type": "text"
      },
      "age":{
        "type": "long"
      },
      "birthday":{
        "type":"date"
      },
      "gender":{
        "type":"text"
      }
    }
  }
}

第二步:将原索引的数据复制给新索引

POST _reindex
{
  "source": {
    "index": "sysconfig"
    
  },
  "dest": {
    "index": "sysconfig2",
    "op_type": "create"
    
  },
  "script": {
    "source": "ctx._source.alias = ctx._source.remove(\"name\")"
    
  }
}

第三步:删除原索引索引

DELETE sysconfig

第四步:给新索引添加别名为原索引

POST _aliases
{
  "actions": [
    {
      "add": {
        "index": "sysconfig2",
        "alias": "sysconfig"
      }
    }
  ]
}

好了,大功告成了!

如果所有的梦想需要钱才能实现,那么只能不谈梦想,只谈钱;努力搬砖!