elasticsearch7.9 搜索模板 restHighLevelClient 操作SearchTemplateAPI用法详解

前言

说到elasticsearch,目前已经更新到最新7.9了,这样用于做全文搜索等。

如果想学得更加精进一点,建议还是看官网,但是只是接触 搜索模板,可以看我以下的内容

https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.5/java-rest-high-search-template.html

本文主要讲的是 Java High Level REST Client 使用该java客户端对 搜索模板进行操作的

生产出测试数据

以下测试均是用java代码接口请求, 可以参考后面 java完整代码

其中 cantemplate-index 为索引名称

POST localhost:8888/template/addData

{
    
    
    "topic":"cantemplate-index",
    "templateJson":{
    
    
        "name":"jack",
        "age":18,
        "sex":"男",
        "address":"广州"
    }
}


{
    
    
    "topic":"cantemplate-index",
    "templateJson":{
    
    
        "name":"jafast",
        "age":21,
        "sex":"男",
        "address":"珠海"
    }
}


{
    
    
    "topic":"cantemplate-index",
    "templateJson":{
    
    
        "name":"lili",
        "age":19,
        "sex":"女",
        "address":"广州"
    }
}

{
    
    
    "topic":"cantemplate-index",
    "templateJson":{
    
    
        "name":"mong",
        "age":20,
        "sex":"女",
        "address":"南宁"
    }
}

{
    
    
    "topic":"cantemplate-index",
    "templateJson":{
    
    
        "name":"xindy",
        "age":21,
        "sex":"男",
        "address":"珠海"
    }
}

创建模板,注意{ {}}语法

模板写法---下面只是参考,跟本文例子无关
{
    
    "templateJson":{
    
    
  "script": {
    
    
    "lang": "mustache",
    "source": "{\"query\": {\"bool\": {\"filter\": [{
    
    {#data-name}}{\"match\": {\"{
    
    {data-name}}\":\"{
    
    {dataname}}\"}}{
    
    {#data-cccc}},{
    
    {/data-cccc}}{
    
    {/data-name}}{
    
    {#data-cccc}}{\"match\": {\"{
    
    {data-cccc}}\":\"{
    
    {datacccc}}\"}}{
    
    {/data-cccc}}]}}}"
  }
}}


由来
{
    
    
  "query": {
    
    
    "bool": {
    
    
      "must": [
        {
    
    
          "match": {
    
    
            "address": "珠海"
          }
        },
        {
    
    
          "range": {
    
    
            "age": {
    
    
              "gt": "18",
              "lt": "22"
            }
          }
        }
      ]
    }
  }
}

创建模板,使用{
    
    {
    
    }}来确定变量
其中 cantemplate-index1为模板名称

POST localhost:8888/template/createEsTemplate/cantemplate1
{
    
    "templateJson":{
    
    
  "script": {
    
    
    "lang": "mustache",
    "source": "{\"query\":{\"bool\":{\"must\":[{\"match\":{\"address\":\"{
    
    {address}}\"}},{\"range\":{\"age\":{\"gt\":\"{
    
    {gt}}\",\"lt\":\"{
    
    {lt}}\"}}}]}}}"
  }
}}

或者

添加判断条件,避免map不传入报错  {
    
    {
    
    #}}{
    
    {
    
    /}}组合来进行判断

{
    
    "templateJson":{
    
    
  "script": {
    
    
    "lang": "mustache",
    "source": "{\"query\":{\"bool\":{\"must\":[{
    
    {#address}}{\"match\":{\"address\":\"{
    
    {address}}\"}}{
    
    {/address}}{
    
    {#gt}}{
    
    {#lt}}{
    
    {#address}},{
    
    {/address}}{\"range\":{\"age\":{\"gt\":\"{
    
    {gt}}\",\"lt\":\"{
    
    {lt}}\"}}}{
    
    {/lt}}{
    
    {/gt}}]}}}"
  }
}}

使用创建的模板进行查询

其中 cantemplate1 为模板名称,cantemplate-index为索引名称

POST localhost:8888/template/useEsTemplate/cantemplate-index/cantemplate1

{
    
    
    "address": "广州",
    "lt": "22",
    "gt":"18"
}

结果
[
    {
    
    
        "address": "广州",
        "sex": "女",
        "name": "lili",
        "id": "72AACAB68DCB42369966861EFAFD4A78",
        "age": 19
    }
]

查看使用模板的ES Query SQL, 需要带上参数

其中 cantemplate1 为索引名称

POST localhost:8888/template/getestemplate/cantemplate1
{
    
    
    "address":"广州",
    "lt":"20",
    "gt":"17"
}

结果
{
    
    
    "query": {
    
    
        "bool": {
    
    
            "must": [
                {
    
    
                    "match": {
    
    
                        "address": "广州"
                    }
                },
                {
    
    
                    "range": {
    
    
                        "age": {
    
    
                            "lt": "22",
                            "gt": "18"
                        }
                    }
                }
            ]
        }
    }
}

精华!!! java完整代码

依赖(注意需要elasticsearch,elasticsearch-rest-client依赖版本)

    <properties>
        <java.version>1.8</java.version>
        <elasticsearch>7.5.1</elasticsearch>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.elasticsearch.client</groupId>
                <artifactId>elasticsearch-rest-high-level-client</artifactId>
                <version>${elasticsearch}</version>
            </dependency>

            <dependency>
                <groupId>org.elasticsearch</groupId>
                <artifactId>elasticsearch</artifactId>
                <version>${elasticsearch}</version>
            </dependency>

            <dependency>
                <groupId>org.elasticsearch.client</groupId>
                <artifactId>elasticsearch-rest-client</artifactId>
                <version>${elasticsearch}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>


    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.62</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

application

spring:
  elasticsearch:
    rest:
      uris: http://localhost:9200 #http://localhost:9200 #http://10.38.2.12:30920
      username: elastic
      password: tjvz7jnhkpdv42fkpqldznsd
server:
  port: 8888

传输类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class EsTemplateDto {
    
    

    private JSONObject templateJson;
}


@Data
@NoArgsConstructor
@AllArgsConstructor
public class EsAddDataDto {
    
    

    private String topic;

    private JSONObject templateJson;

}

控制器

/**
 * @author czchen
 * @version 1.0
 * @date 2020/9/7 11:46
 */
@RestController
@RequestMapping("/template")
@Slf4j
public class EsTemplate {
    
    


    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @PostMapping("/addData")
    public String addData(@RequestBody EsAddDataDto esAddDataDto){
    
    

        //创建请求
        IndexRequest request = new IndexRequest(esAddDataDto.getTopic());
        //规则 put /test_index/_doc/1
        request.id(UUID.randomUUID().toString().replaceAll("-", "").toUpperCase());
        request.timeout(TimeValue.timeValueSeconds(1));
        //将数据放入请求 json
        IndexRequest source = request.source(esAddDataDto.getTemplateJson(), XContentType.JSON);
        //客户端发送请求
        IndexResponse response = null;
        try {
    
    
            response = restHighLevelClient.index(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
        log.info("添加数据成功 索引为: {}, response 状态: {}, id为: {}",esAddDataDto.getTopic(),response.status().getStatus(), response.getId());
        return "添加数据";
    }


    /**
     * es模板对象
     *
     * @param templateid 模板名称
     * @param esTemplateDto 模板对象
     * @return 创建模板结果
     */
    @PostMapping("/createEsTemplate/{templateid}")
    public String createEsTemplate(@PathVariable String templateid, @RequestBody EsTemplateDto esTemplateDto){
    
    

        Request scriptRequest = new Request("POST", "_scripts/"+templateid);

        String templateJsonString = esTemplateDto.getTemplateJson().toString();
        scriptRequest.setJsonEntity(templateJsonString);

        RestClient restClient = restHighLevelClient.getLowLevelClient();

        try {
    
    
            Response response = restClient.performRequest(scriptRequest);
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }

        return "创建模板成功";
    }


    @PostMapping("/getestemplate/{templateid}")
    public String getEsTemplate(@PathVariable String templateid,@RequestBody Map<String,Object> map){
    
    
        SearchTemplateRequest request = new SearchTemplateRequest();

        request.setScriptType(ScriptType.STORED);

        request.setScript(templateid);

        request.setSimulate(true);

        request.setScriptParams(map);

        SearchTemplateResponse renderResponse = null;

        try {
    
    
            renderResponse = restHighLevelClient.searchTemplate(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
        BytesReference source = renderResponse.getSource();

        return source.utf8ToString();
    }



    /**
     * 利用模板进行数据查找
     *
     * @param topic 主题
     * @param templateid 模板名称
     * @param map 查找的k_v
     * @return 朝招对象
     */
    @PostMapping("/useEsTemplate/{topic}/{templateid}")
    public List<Map<String, Object>> useEsTemplate(@PathVariable String topic,@PathVariable String templateid, @RequestBody Map<String,Object> map){
    
    

        String indexTopic = topic;

        SearchTemplateRequest request = new SearchTemplateRequest();
        request.setRequest(new SearchRequest(indexTopic));

        request.setScriptType(ScriptType.STORED);
        request.setScript(templateid);

        request.setScriptParams(map);

        //request.setSimulate(true);

        SearchTemplateResponse response = null;
        try {
    
    
            response = restHighLevelClient.searchTemplate(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }

        SearchResponse searchResponse = response.getResponse();

        //BytesReference source = response.getSource();

        //打印出储存的模板
        //System.out.println(source.utf8ToString());

        SearchHits searchHits = searchResponse.getHits();

        List<Map<String, Object>> maps = setSearchResponse(searchResponse, "");

        return maps;
        //return null;
    }

    public List<Map<String, Object>> setSearchResponse(SearchResponse searchResponse, String highlightField) {
    
    
        //解析结果
        ArrayList<Map<String,Object>> list = new ArrayList<>();
        for (SearchHit hit : searchResponse.getHits().getHits()) {
    
    
            Map<String, HighlightField> high = hit.getHighlightFields();
            HighlightField title = high.get(highlightField);

            hit.getSourceAsMap().put("id", hit.getId());

            Map<String, Object> sourceAsMap = hit.getSourceAsMap();//原来的结果
            //解析高亮字段,将原来的字段换为高亮字段
            if (title!=null){
    
    
                Text[] texts = title.fragments();
                String nTitle="";
                for (Text text : texts) {
    
    
                    nTitle+=text;
                }
                //替换
                sourceAsMap.put(highlightField,nTitle);
            }
            list.add(sourceAsMap);
        }
        return list;
    }

}

附带原生 ES Rest Template

创建模板

其中 template1 为模板名称

POST _scripts/template1

{
    
    
  "script": {
    
    
    "lang": "mustache",
    "source": "{\"query\":{\"bool\":{\"must\":[{\"match\":{\"address\":\"{
    
    {address}}\"}},{\"range\":{\"age\":{\"gt\":\"{
    
    {gt}}\",\"lt\":\"{
    
    {lt}}\"}}}]}}}"
  }
}

{
    
    
    "acknowledged": true
}

查询模板

以下为固定的格式
POST _render/template

{
    
    
  "source": "{\"query\":{\"bool\":{\"must\":[{\"match\":{\"address\":\"{
    
    {address}}\"}},{\"range\":{\"age\":{\"gt\":\"{
    
    {gt}}\",\"lt\":\"{
    
    {lt}}\"}}}]}}}",
  "params": {
    
    
    "address":"广州",
    "lt":"22",
    "gt":"18"
    }
}

或者

其中 template1 为模板名称

POST _render/template/template1
{
    
    
  "params": {
    
    
    "address":"广州",
    "lt":"22",
    "gt":"18"
    }
}

结果
{
    
    
  "template_output": {
    
    
    "query": {
    
    
      "bool": {
    
    
        "must": [
          {
    
    
            "match": {
    
    
              "address": "广州"
            }
          },
          {
    
    
            "range": {
    
    
              "age": {
    
    
                "gt": "18",
                "lt": "22"
              }
            }
          }
        ]
      }
    }
  }
}

使用模板进行查询

其中 cantemplate-index 为索引名称
template1 为搜索模板名称

POST cantemplate-index/_search/template/
{
    
    
  "id": "template1", 
  "params": {
    
    
    "address":"广州",
    "lt":"23",
    "gt":"17"
  }
}


结果

{
    
    
  "took": 2,
  "timed_out": false,
  "_shards": {
    
    
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    
    
    "total": {
    
    
      "value": 2,
      "relation": "eq"
    },
    "max_score": 2.7509375,
    "hits": [
      {
    
    
        "_index": "cantemplate-index",
        "_type": "_doc",
        "_id": "FCDA53DD7B2840F19CE2C0E2FDE5049C",
        "_score": 2.7509375,
        "_source": {
    
    
          "address": "广州",
          "sex": "男",
          "name": "jack",
          "age": 18
        }
      },
      {
    
    
        "_index": "cantemplate-index",
        "_type": "_doc",
        "_id": "72AACAB68DCB42369966861EFAFD4A78",
        "_score": 2.7509375,
        "_source": {
    
    
          "address": "广州",
          "sex": "女",
          "name": "lili",
          "age": 19
        }
      }
    ]
  }
}

后记

大部分的程序员,都是面向百度或者谷歌进行编程的,而网上的资料乱七八糟,有时候找起来让人难受,于是本人无偿进行资料收集的工作,大部分资料都是本人实打实收集的而且测试过,大家不用怀疑准确性,奈何能力有限,免于遗漏,希望读者可以在评论或者私信我,进行改正,大家一起为互联网技术做贡献。


收集资料枯燥无味,如果本文对你有帮助,可以点个赞,这个也是对我最大的鼓励和赞许。

本人行不改名坐不改姓,潮汕的灿灿展

立志在互联网这一行,做出自己的贡献


猜你喜欢

转载自blog.csdn.net/qq_34168515/article/details/108352272