elasticsearch Java High Level REST Client - Search Template

生产出测试数据

以下测试均是用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
        }
      }
    ]
  }
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。