提示:以下是本篇文章正文内容,下面案例可供参考
我们常见的搜索类型有
1.time 可以有很多格式的时间类型,我这里使用了最常用的格式, 2.keyword,使用在已经确定的枚举类型的,例如男、女
3.text,使用在模糊查找的字段,例如文章内容等
4.list,使用在1对多的关系中,例如一个人的标签,可爱、善良
这里我都新建了这几种类型,可以参考如何使用。
新建索引名称为test,属性有name,nameType,time 和一个tag标签list
PUT /test { "mappings": { "properties": { "name": { "type": "text" }, "nameType": { "type": "text" }, "time": { "type": "date", "format": "yyyy-MM-dd HH:mm:ss || yyyy-MM-dd || yyyy/MM/dd HH:mm:ss|| yyyy/MM/dd ||epoch_millis" }, "tags": { "properties": { "id": {"type":"keyword"}, "tagName": { "type": "text" } } } } } }
DELETE /test
GET /test/_search { "query": {"match_all": { }} }
GET /test
代码如下(示例):
<properties> <java.version>1.8</java.version> <elasticsearch.version>7.14.1</elasticsearch.version> </properties>
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.20</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.9</version> </dependency> <dependency> <groupId>apache-beanutils</groupId> <artifactId>commons-beanutils</artifactId> <version>1.7.0</version> </dependency>
主要是spring-boot-starter-data-elasticsearch,其他有用到就一起粘贴下来了。使用的springboot版本为
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.4</version> <relativePath/> <!-- lookup parent from repository --> </parent>
建立如下的配置,在control层就可以直接注入使用连接
一般es的端口为9200,如果有账号密码的也可以使用账号密码连接
这里就不展示了,可以看看api就知道了。
代码如下(示例):
package com.example.springdemo.demo.conifg; import org.apache.http.HttpHost; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestHighLevelClient; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class EsConfig { @Bean("restHighLevelClient") public RestHighLevelClient esRestClient(){ RestHighLevelClient client = new RestHighLevelClient( RestClient.builder( //在这里配置你的elasticsearch的地址 new HttpHost("123.xx.xx.xxx", 9200, "http") ) ); return client; } }
@Autowired private RestHighLevelClient restHighLevelClient;
这里只介绍了单个插入,批量插入使用client.bulk方法即可
private String insertData(EsModel esModel) throws IOException { //要插入的索引名称test IndexRequest request = new IndexRequest("test"); request.id(UUID.randomUUID().toString()); request.timeout(TimeValue.timeValueSeconds(1)); request.timeout("1s"); //将我们的数据放入请求,json request.source(JSON.toJSONString(esModel),XContentType.JSON); //request.source(describe); System.out.println("json:"+JSON.toJSONString(esModel)); //客服端发送请求 IndexResponse index = restHighLevelClient.index(request, RequestOptions.DEFAULT); request.source(JSON.toJSONString(esModel),XContentType.JSON); String result = index.toString()+"/n"+index.toString(); System.out.println(result); return result; }
这里的插入格式es支持两种格式,一种是json格式的,如上面的写法,一种是map格式的,
JSON.parseObject(JSON.toJSONString(user), Map.class);
map格式的可以使用json的工具类直接转换即可。
@RequestMapping("/testInsert") String testInsert() throws IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { StringBuilder sb = new StringBuilder(); EsModel user = new EsModel(); user.setName("王小明"); user.setNameType("男"); user.setTime(new Date()); List<Tag> tags = new ArrayList<>(); Tag tag = new Tag(); tag.setId(UUID.randomUUID().toString()); tag.setTagName("活泼"); Tag tag1 = new Tag(); tag1.setId(UUID.randomUUID().toString()); tag1.setTagName("开朗"); Tag tag11= new Tag(); tag11.setId(UUID.randomUUID().toString()); tag11.setTagName("活泼2"); tags.add(tag); tags.add(tag1); tags.add(tag11); user.setTags(tags); String s1 = insertData(user); sb.append(s1).append("/n"); EsModel user2 = new EsModel(); user2.setName("王小二"); user2.setNameType("男"); user2.setTime(new Date()); List<Tag> tags4 = new ArrayList<>(); Tag tag4 = new Tag(); tag4.setId(UUID.randomUUID().toString()); tag4.setTagName("高富活泼"); Tag tag5 = new Tag(); tag5.setId(UUID.randomUUID().toString()); tag5.setTagName("英俊"); tags4.add(tag4); tags4.add(tag5); user2.setTags(tags4); String s3 = insertData(user2); sb.append(s3).append("/n"); EsModel user1 = new EsModel(); user1.setName("王小红"); user1.setNameType("女"); user1.setTime(new Date()); List<Tag> tags1 = new ArrayList<>(); Tag tag2 = new Tag(); tag2.setId(UUID.randomUUID().toString()); tag2.setTagName("漂亮"); Tag tag3 = new Tag(); tag3.setId(UUID.randomUUID().toString()); tag3.setTagName("可爱"); tags1.add(tag3); tags1.add(tag2); user1.setTags(tags1); String s = insertData(user1); sb.append(s).append("/n"); return sb.toString(); }
这里需要注意的是,如果格式是时间格式,我们需要在实体上加个jsonfield注解否则转换成string的时候会报错。实体类如下
package com.example.springdemo.demo.model; import com.alibaba.fastjson.annotation.JSONField; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; import org.springframework.data.elasticsearch.annotations.DateFormat; import org.springframework.data.elasticsearch.annotations.Field; import org.springframework.data.elasticsearch.annotations.FieldType; import java.io.Serializable; import java.text.Format; import java.util.Date; import java.util.List; @Data public class EsModel implements Serializable { private String name; private String nameType; // @Field(type = FieldType.Date, format= DateFormat.custom,pattern ="yyyy-MM-dd HH:mm:ss") // @JsonFormat(shape = JsonFormat.Shape.STRING, pattern ="yyyy-MM-dd HH:mm:ss",timezone="GMT+8") @JSONField(format="yyyy-MM-dd HH:mm:ss") private Date time; private List<Tag> tags; }
package com.example.springdemo.demo.model; import lombok.Data; @Data public class Tag { private String id; private String tagName; }
执行插入指令显示如下
http://localhost:8008/search/testInsert
去kibana查询下数据是否插入
执行上面的查询所有数据指令可以看到数据已经成功插入
接下来我们可以进行查询了,这里我们主要用的是中文查询,中文搜索的时候,和查询的时候都可以指定分词器,分词器的作用其实就是可以智能的把语句分成不同的词语索引,例如我爱中国,可以分解成,我,爱,中国,如果不加分词器,则会分解成我,爱,中,国,和更多的组合,一般会使用分词器,我这里就不使用了。
这样在搜索的时候就可以更精确的查找到用户想要的结果。
我们可以在kibana测试一下
GET _analyze {"text":"我爱中国"}
使用分词器分词
GET _analyze {"analyzer":"ik_max_word", "text":"我爱中国"}
实际项目使用的时候往往不会像一般简单教程里面的这么简单,分页,模糊查询,高亮,排序,是基本的要求,所以我就构造了下面的查询
这里的查询条件构造如下:
查询一个boolquery,也就是一个是否的条件查询
这里查询为:并且(must) nametype 含有男
并且(代码里面用must表示)
(
或者(代码用shuld) tags.tagName 中含有 活字
)
list里面的字段用list名字.属性表示。
@RequestMapping("/testSearch") String contextLoads() throws IOException { //1、创建查询请求,规定查询的索引 SearchRequest request = new SearchRequest("test"); //2、创建条件构造 SearchSourceBuilder builder = new SearchSourceBuilder(); //3、构造条件 BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder(); boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("nameType","男")); BoolQueryBuilder condition = new BoolQueryBuilder(); condition.should(QueryBuilders.matchPhraseQuery("tags.tagName","活")); boolQueryBuilder.must(condition); builder.query(boolQueryBuilder); //高亮查询 HighlightBuilder highlightBuilder = new HighlightBuilder(); HighlightBuilder.Field field = new HighlightBuilder.Field("tags.tagName"); highlightBuilder.field(field); highlightBuilder.requireFieldMatch(false); // highlightBuilder.preTags("<em>"); // highlightBuilder.postTags("</em>"); highlightBuilder.preTags("<span style='color:red'>"); highlightBuilder.postTags("</span>"); builder.highlighter(highlightBuilder); //指定返回的字段 String[] fetch ={"name","nameType","tags.tagName"}; builder.fetchSource(fetch,null); builder.from(0); builder.size(10); //根据匹配度排序 builder.sort("_score",SortOrder.DESC); //根据时间排序,asc升序 builder.sort("time", SortOrder.DESC); //4、将构造好的条件放入请求中 request.source(builder); //5、开始执行发送request请求 SearchResponse searchResponse = restHighLevelClient.search(request, RequestOptions.DEFAULT); //6、开始处理返回的数据 SearchHit[] hits = searchResponse.getHits().getHits(); StringBuilder sb = new StringBuilder(); for (SearchHit hit : hits) { Map<String, HighlightField> highlightFields = hit.getHighlightFields(); System.out.println("highlight"+highlightFields); HighlightField content = highlightFields.get("tags.tagName"); //原始数据 Map<String, Object> sourceAsMap = hit.getSourceAsMap(); System.out.println("sourcemap"+sourceAsMap); //高亮的字段替换 if (content!=null){ Text[] fragments = content.fragments(); sourceAsMap.put("tags",Arrays.asList(fragments)); } sb.append(sourceAsMap); } System.out.println("sb"+ sb.toString()); return sb.toString(); }
这里的高亮显示,但是页面上不显示出来,这里换成了页面可以显示出来的格式
查询的结果如图所示
例如:以上就是今天要讲的内容,本文仅仅简单介绍了es的基本使用,更多的查询例如termsquery精确查找,和fuzzyquery近似查找,例如国中,可以帮你搜索出中国,还有范围查询等等高级使用,可以查询es官方文档,这里仅作为一个入门介绍,如果该文章对你有用,可以点赞一下呀,比较写文章不容易,还是要花些时间的。