文章目录
前言
说到elasticsearch,目前已经更新到最新7.9了,这样用于做全文搜索等。
如果想学得更加精进一点,建议还是看官网,但是只是接触 搜索模板,可以看我以下的内容
本文主要讲的是 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
}
}
]
}
}
后记
大部分的程序员,都是面向百度或者谷歌进行编程的,而网上的资料乱七八糟,有时候找起来让人难受,于是本人无偿进行资料收集的工作,大部分资料都是本人实打实收集的而且测试过,大家不用怀疑准确性,奈何能力有限,免于遗漏,希望读者可以在评论或者私信我,进行改正,大家一起为互联网技术做贡献。
收集资料枯燥无味,如果本文对你有帮助,可以点个赞,这个也是对我最大的鼓励和赞许。
本人行不改名坐不改姓,潮汕的灿灿展
立志在互联网这一行,做出自己的贡献