本文使用的是springboot 2.2.x版本,elasticsearch使用的是6.8版本
官方文档参考:https://docs.spring.io/spring-data/elasticsearch/docs/4.2.7/reference/html/#new-features
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-elasticsearchartifactId>
dependency>
@Configuration
public class RestClientConfig {
/**
* 此配置在官网cv过来的,表示注册高级客户端RestHighLevelClient,它默认走的是9200端口
* transportClient客户端是基于tcp协议的,走的是es的9300端口,在es7版本后,已经不推荐使用transportClient客户端
* 可能还有人有疑问?注入的bean名字是client,那么注入时会不会有问题呢?这个无所谓,
* 当使用@Autowired注入bean时,会先按照类型进行注入,如果有且仅有一个此类型的bean,
* 那么就直接注入了,如果有多个同类型的bean,
* 那么就需要使用@Qualifier指定bean名字注入使用,此案例中这个RestHighLevelClient在容器中只有
* 一个,直接使用@Autowired就能注入使用了
* @return
*/
@Bean
RestHighLevelClient client() {
ClientConfiguration clientConfiguration = ClientConfiguration.builder()
.connectedTo("填写es服务的ip+端口")
.build();
return RestClients.create(clientConfiguration).rest();
}
}
spring:
elasticsearch:
rest:
uris: 106.52.98.231:19200
/**
* 插入数据
* @throws IOException
*/
@Test
public void test2() throws IOException {
Student student = new Student();
student.setAge(13);
student.setBir(new Date());
student.setDetail("老师");
student.setHobby("网吧");
student.setId(UUID.randomUUID().toString());
student.setName("贺粪");
student.setRemark("男");
IndexRequest indexRequest = new IndexRequest("ems", "emp");
String jsonString = JSON.toJSONString(student);
indexRequest.source(jsonString,XContentType.JSON);
IndexResponse response = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
System.out.println(response.status());
}
/**
* 查询数据
* @throws IOException
* 调用过程:QueryBuilders-->SearchSourceBuilder-->SearchRequest
* 用于构建查询条件-->封装到查询器-->封装条件到请求体
*/
@Test
public void test3() throws IOException {
//构建一个查询请求体
SearchRequest searchRequest = new SearchRequest("ems");
//构建一个查询器
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//将查询条件都写在这里
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
//写多个条件使用多个must拼接条件
boolQueryBuilder.must(QueryBuilders.termQuery("hobby","网吧"));
//boolQueryBuilder.must(QueryBuilders.termQuery("age",11));
boolQueryBuilder.filter(QueryBuilders.rangeQuery("age").gte(10).lte(111));
//将查询条件放在查询器里
searchSourceBuilder.query(boolQueryBuilder)
.highlighter(new HighlightBuilder().field("*").requireFieldMatch(false).preTags("").postTags("")) //field("*").requireFieldMatch(false)表示查询的所有字段包含某个词都进行高亮
.sort("age", SortOrder.DESC) //按照age倒叙排序
.from(0) //0,表示第一页
.size(10) //10表示每页展示10条数据
.postFilter(QueryBuilders.matchAllQuery()); //过滤出全部数据,并不是过滤掉
//将查询器放在请求体内
searchRequest.types("emp").source(searchSourceBuilder);
//执行请求
SearchResponse result = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
//获取数据
SearchHit[] hits = result.getHits().getHits();
for (SearchHit hit : hits) {
//将查询出来的数据转换成map,通过key-value的方式获取值
System.out.println(hit.getSourceAsMap());
//将查询出来的数据转成json串,如果想转成对象可以使用fastjsoon工具包
System.out.println(hit.getSourceAsString());
//这个展示的是所有符合高亮条件的字段
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
System.out.println("===========================================================");
//遍历出一条文档中高亮的字段,可能会有多个字段所以使用for循环
// {detail=[detail], fragments[[去网吧上网打游戏,网吧消费]], hobby=[hobby], fragments[[网吧]]}
for (String key : highlightFields.keySet()) {
HighlightField highlightField = highlightFields.get(key);
Text fragment = highlightField.getFragments()[0];
System.out.println(fragment);
}
}
}
//删除数据
@Test
public void test4() throws IOException {
DeleteRequest deleteRequest = new DeleteRequest("ems","emp","EbFnfn0BB7Hd6_ABwKCu");
restHighLevelClient.delete(deleteRequest,RequestOptions.DEFAULT);
}
//更新数据
@Test
public void test5() throws IOException {
//先查询出数据,然后再更新
SearchRequest searchRequest = new SearchRequest("ems");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.matchQuery("name","贺飞"));
searchRequest.source(searchSourceBuilder);
SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
//我知道这块只有一条数据,所以直接获取0号索引的数据
SearchHit hit = search.getHits().getHits()[0];
//这条文档的唯一标识,取出来用户后面的更新操作使用
String id = hit.getId();
//将文档获取出来转成json串
String sourceAsString = hit.getSourceAsString();
//将json串转换成对象
Student student = JSON.parseObject(sourceAsString, Student.class);
//将原来的name修改成-->贺飞
student.setName("贺飞");
student.setDetail("好老师篮球篮球好篮球");
//将对象转换成json串,然后用于更新
String jsonString = JSON.toJSONString(student);
//更新文档
UpdateRequest updateRequest = new UpdateRequest("ems","emp",id);
updateRequest.doc(jsonString,XContentType.JSON);
restHighLevelClient.update(updateRequest,RequestOptions.DEFAULT);
}
注意:spring data elasticsearch 在4.0版本后已经将@document注解的type属性弃用
Keyword | Sample | Elasticsearch Query String |
---|---|---|
And |
findByNameAndPrice |
{"bool" : {"must" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}} |
Or |
findByNameOrPrice |
{"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}} |
Is |
findByName |
{"bool" : {"must" : {"field" : {"name" : "?"}}}} |
Not |
findByNameNot |
{"bool" : {"must_not" : {"field" : {"name" : "?"}}}} |
Between |
findByPriceBetween |
{"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : ?,"include_lower" : true,"include_upper" : true}}}}} |
LessThanEqual |
findByPriceLessThan |
{"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}} |
GreaterThanEqual |
findByPriceGreaterThan |
{"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}} |
Before |
findByPriceBefore |
{"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}} |
After |
findByPriceAfter |
{"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}} |
Like |
findByNameLike |
{"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}} |
StartingWith |
findByNameStartingWith |
{"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}} |
EndingWith |
findByNameEndingWith |
{"bool" : {"must" : {"field" : {"name" : {"query" : "*?","analyze_wildcard" : true}}}}} |
Contains/Containing |
findByNameContaining |
{"bool" : {"must" : {"field" : {"name" : {"query" : "**?**","analyze_wildcard" : true}}}}} |
In |
findByNameIn (Collection |
{"bool" : {"must" : {"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"name" : "?"}} ]}}}} |
NotIn |
findByNameNotIn (Collection |
{"bool" : {"must_not" : {"bool" : {"should" : {"field" : {"name" : "?"}}}}}} |
Near |
findByStoreNear |
Not Supported Yet ! |
True |
findByAvailableTrue |
{"bool" : {"must" : {"field" : {"available" : true}}}} |
False |
findByAvailableFalse |
{"bool" : {"must" : {"field" : {"available" : false}}}} |
OrderBy |
findByAvailable TrueOrderByNameDesc |
{"sort" : [{ "name" : {"order" : "desc"} }],"bool" : {"must" : {"field" : {"available" : true}}}} |
/**
* 只要遵循上面的语法形式,只要定义出接口,就能直接调用查询数据
*/
public interface BookRepository extends ElasticsearchRepository<Book,String> {
//根据作者查询
List<Book> findByAuthor(String keyword);
//根据内容查询
List<Book> findByContent(String keyword);
//根据内容和名字查
List<Book> findByNameAndContent(String name,String content);
List<Book> findByNameAndContentAndPrice(String name,String content,Double price);
//根据内容或名称查询
List<Book> findByNameOrContent(String name,String content);
//范围查询
List<Book> findByPriceBetween(Double start,Double end);
//查询名字以xx开始的
List<Book> findByNameStartingWith(String name);
//查询某个字段值是否为false
List<Book> findByNameFalse();
//.......
}
{detail=[detail], fragments[[好老师>篮球>>篮球>好>篮球>]], hobby=[hobby], fragments[[>篮球>]]}