ES客户端文档操作
1.引入依赖
<!--spring-boot-data-es-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
在导入依赖后需要在yml文件中配置es的地址
spring:
elasticsearch:
rest:
uris: http://101.35.161.133:9200
使用java文档操作es,可以使用以下对象
- ElasticsearchOperations
- RestHighLevelClient **推荐
2.ElasticsearchOperations使用
2.1创建索引对象
package com.example.demo.entity;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
/**
* @Document: 将这个类对象转为 es 中一条文档进行录入
* indexName: 用来指定文档的索引名称
* createIndex: 用来指定是否创建索引
*/
@Data
@Document(indexName = "students",createIndex = true)
public class Student {
@Id//用来将放入对象 id 值 作为文档_id 进行映射
private Long id;
@Field(type = FieldType.Keyword)//不可以用作分词
private String name;
@Field(type = FieldType.Keyword)
private String sex;
@Field(type = FieldType.Integer)
private Integer age;
@Field(type = FieldType.Text)//可以用做分词
private String desc;
}
创建测试类,自动注入ElasticsearchOperations对象,执行save操作
@SpringBootTest
public class StudentTest {
@Autowired
private ElasticsearchOperations elasticsearchOperations;
@Test
public void createData(){
Student student=new Student();
student.setId(1L);
student.setName("张三");
student.setSex("男");
student.setAge(18);
student.setDesc("大家好我是张三,我是一名画家");
elasticsearchOperations.save(student);
}
}
查看es
2.2查询一条数据
@Test
public void findOne(){
Student student = elasticsearchOperations.get("1", Student.class);
System.out.println("student = " + student);
}
2.3查询所有
@Test
public void findAll() throws JsonProcessingException {
SearchHits<Student> search = elasticsearchOperations.search(Query.findAll(), Student.class);
System.out.println("search.getMaxScore() = " + search.getMaxScore());
System.out.println("search.getTotalHits() = " + search.getTotalHits());
for (SearchHit<Student> studentSearchHit : search) {
System.out.println(new ObjectMapper().writeValueAsString(studentSearchHit.getContent()));
}
}
2.4删除一条文档
@Test
public void deleteOne(){
Student student=new Student();
student.setId(1L);
elasticsearchOperations.delete(student);
}
2.5删除所有
@Test
public void deleteAll(){
elasticsearchOperations.delete(Query.findAll(), Student.class);
}
3.RestHighLevelClient 的使用
RestHighLevelClient 的使用和kibana的使用基本相同,所以是推荐的使用方式。
3.1RestHighLevelClient 的基本操作
3.1.1创建索引
使用RestHighLevelClient 创建索引,需要先创建好索引字段内容
PUT /products
{
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "ik_max_word"
},
"price": {
"type": "double"
},
"create_at": {
"type": "date"
},
"description": {
"type": "text",
"analyzer": "ik_max_word"
}
}
}
}
将索引的内容放到代码中,再执行创建索引操作
@Test
public void testIndexAndMapping() throws IOException {
CreateIndexRequest createIndexRequest = new CreateIndexRequest("products");
createIndexRequest.mapping("{\"properties\":{\"title\":{\"type\":\"keyword\"},\"price\":{\"type\":\"double\"},\"create_at\":{\"type\":\"date\"},\"description\":{\"type\":\"text\",\"analyzer\":\"ik_max_word\"}}}", XContentType.JSON);
CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
System.out.println("createIndexResponse = " + createIndexResponse);
restHighLevelClient.close();
}
使用kibana看到索引创建成功
3.1.2删除索引
删除指定索引
@Test
public void testdeleteIndex() throws IOException {
AcknowledgedResponse acknowledgedResponse = restHighLevelClient.indices().delete(new DeleteIndexRequest("products"), RequestOptions.DEFAULT);
System.out.println("acknowledgedResponse = " + acknowledgedResponse.toString());
}
可以看到索引被删除,执行查看索引将会报错
3.1.3创建文档
在创建索引后,在kibaba中创建出一条数据备用
PUT /products/_doc/1
{
"title":"脆司令",
"price":1.5,
"create_at":"2021-12-12",
"description":"脆司令非常好吃"
}
创建测试类将RestHighLevelClient注入,执行创建索引并插入数据,没有指定id,会自动生成id
@SpringBootTest
public class RestHighLevClientForDocumentTests{
@Autowired
private RestHighLevelClient restHighLevelClient;
@Test
public void testCreate() throws IOException {
IndexRequest indexRequest = new IndexRequest("products");
indexRequest.source("{\"title\":\"脆司令\",\"price\":1.5,\"create_at\":\"2021-12-12\",\"description\":\"脆司令非常好吃\"}", XContentType.JSON);
IndexResponse index = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
System.out.println("index = " + index);
}
}
3.1.4根据id查询
@Test
public void testQueryById() throws IOException {
GetRequest getRequest = new GetRequest("products", "BaTgKIEBrV6nA_doTtkg");
GetResponse getResponse = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
System.out.println("id:"+getResponse.getId());
System.out.println("getResponse.getSourceAsString() = " + getResponse.getSourceAsString());
}
3.1.5根据id修改
@Test
public void testUpdate() throws IOException {
UpdateRequest updateRequest = new UpdateRequest("products", "BaTgKIEBrV6nA_doTtkg");
updateRequest.doc("{\"price\":0.5}",XContentType.JSON);
UpdateResponse update = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
System.out.println("update = " + update);
}
3.1.6根据id删除
@Test
public void testDelete() throws IOException {
DeleteResponse products = restHighLevelClient.delete(new DeleteRequest("products", "1"), RequestOptions.DEFAULT);
System.out.println("products = " + products);
}
3.2综合查询
进行查询之前需要准备查询数据
3.2.1创建索引
PUT /products
{
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "ik_max_word"
},
"price": {
"type": "double"
},
"create_at": {
"type": "date"
},
"description": {
"type": "text",
"analyzer": "ik_max_word"
}
}
}
}
3.2.2添加数据
PUT /products/_doc/1
{
"title":"脆司令",
"price":1.5,
"create_at":"2021-12-12",
"description":"脆司令非常好吃"
}
PUT /products/_doc/2
{
"title":"荷兰豆",
"price":1.5,
"create_at":"2021-12-12",
"description":"荷兰豆令非常好吃"
}
PUT /products/_doc/3
{
"title":"鱼豆腐",
"price":1.5,
"create_at":"2021-12-12",
"description":"鱼豆腐非常好吃"
}
PUT /products/_doc/4
{
"title":"小鱼干",
"price":1.5,
"create_at":"2021-12-12",
"description":"小鱼干非常好吃"
}
3.2.3查询所有
创建RestHighLevClientForSearchTests测试类
@SpringBootTest
public class RestHighLevClientForSearchTests {
@Autowired
private RestHighLevelClient restHighLevelClient;
@Test
public void testMatchAll() throws IOException {
SearchRequest searchRequest = new SearchRequest("products");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.matchAllQuery());
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("总条数:"+searchResponse.getHits().getTotalHits().value);
System.out.println("最大得分:"+searchResponse.getHits().getMaxScore());
SearchHit[] hits = searchResponse.getHits().getHits();
for (SearchHit hit : hits) {
String id = hit.getId();
System.out.println("id:"+id+"source:"+hit.getSourceAsString());
}
}
}
查询结果:
3.2.4使用分词查询
@Test
public void testQuery() throws IOException {
SearchRequest searchRequest = new SearchRequest("products");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.termQuery("description","司令"));
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("符合条件总数:"+searchResponse.getHits().getTotalHits().value);
System.out.println("获取文档最大分数:"+searchResponse.getHits().getTotalHits().value);
SearchHit[] hits = searchResponse.getHits().getHits();
for (SearchHit hit : hits) {
System.out.println("id:"+hit.getId()+" source:"+hit.getSourceAsString());
}
}
3.2.5根据加个查询,查询数据高亮
@Test
public void testSearch() throws IOException {
SearchRequest searchRequest = new SearchRequest("products");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.requireFieldMatch(false).field("description").field("title").preTags("<span style='color:red'>").postTags("</span>");
sourceBuilder.query(QueryBuilders.termQuery("description","好吃"))
.from(0)
.size(10)
.sort("price", SortOrder.ASC)
.fetchSource(new String[]{},new String[]{"create_at"})
.highlighter(highlightBuilder);
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("符合条件总数:"+searchResponse.getHits().getTotalHits().value);
System.out.println("获取文档最大分数:"+searchResponse.getHits().getTotalHits().value);
SearchHit[] hits = searchResponse.getHits().getHits();
for (SearchHit hit : hits) {
System.out.println("id:"+hit.getId()+" source:"+hit.getSourceAsString());
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
if(highlightFields.containsKey("description")){
System.out.println("description高亮结果:"+highlightFields.get("description").fragments()[0]);
}
if(highlightFields.containsKey("title")){
System.out.println("title高亮的结果:"+highlightFields.get("title").fragments()[0]);
}
}
}
查询结果:
3.2.6过滤器查询
@Test
public void testFilterQuery() throws IOException {
SearchRequest searchRequest = new SearchRequest("products");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder
.query(QueryBuilders.matchAllQuery())
.postFilter(QueryBuilders.termQuery("description","豆腐"));
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("符合条件总数:"+searchResponse.getHits().getTotalHits().value);
System.out.println("获取文档最大分数:"+searchResponse.getHits().getTotalHits().value);
SearchHit[] hits = searchResponse.getHits().getHits();
for (SearchHit hit : hits) {
System.out.println("id:"+hit.getId()+" source:"+hit.getSourceAsString());
}
}
3.2.7封装查询函数
public void query(QueryBuilder queryBuilder) throws IOException {
SearchRequest searchRequest = new SearchRequest("products");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(queryBuilder);
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("符合条件总数:"+searchResponse.getHits().getTotalHits().value);
System.out.println("获取文档最大分数:"+searchResponse.getHits().getTotalHits().value);
SearchHit[] hits = searchResponse.getHits().getHits();
for (SearchHit hit : hits) {
System.out.println("id:"+hit.getId()+" source:"+hit.getSourceAsString());
}
}
查询
@Test
public void testQuery2() throws IOException {
query(QueryBuilders.termQuery("description","司令"));
query(QueryBuilders.rangeQuery("price").gt(0).lte(1.66));
query(QueryBuilders.prefixQuery("description","脆司令"));
query(QueryBuilders.wildcardQuery("title","脆*"));
query(QueryBuilders.idsQuery().addIds("1").addIds("2"));
query(QueryBuilders.multiMatchQuery("非常不错","title","description"));
}
查询结果:
3.3聚合查询
3.3.1准备数据
创建索引
PUT /fruit
{
"mappings": {
"properties": {
"title":{
"type": "keyword"
},
"price":{
"type":"double"
},
"description":{
"type": "text",
"analyzer": "ik_max_word"
}
}
}
}
添加数据
PUT /fruit/_bulk
{"index":{}}
{"title" : "面包","price" : 19.9,"description" : "小面包非常好吃"}
{"index":{}}
{"title" : "旺仔牛奶","price" : 29.9,"description" : "非常好喝"}
{"index":{}}
{"title" : "日本豆","price" : 19.9,"description" : "日本豆非常好吃"}
{"index":{}}
{"title" : "小馒头","price" : 19.9,"description" : "小馒头非常好吃"}
{"index":{}}
{"title" : "大辣片","price" : 39.9,"description" : "大辣片非常好吃"}
{"index":{}}
{"title" : "透心凉","price" : 9.9,"description" : "透心凉非常好喝"}
{"index":{}}
{"title" : "小浣熊","price" : 19.9,"description" : "童年的味道"}
{"index":{}}
{"title" : "海苔","price" : 19.9,"description" : "海的味道"}
3.3.2根据加个聚合
@Test
public void testAggs() throws IOException {
SearchRequest searchRequest = new SearchRequest("fruit");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder
.query(QueryBuilders.matchAllQuery())
.aggregation(AggregationBuilders.terms("price_group").field("price"))
.size(0);
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
Aggregations aggregations = searchResponse.getAggregations();
ParsedDoubleTerms parsedDoubleTerms = aggregations.get("price_group");
List<? extends Terms.Bucket> buckets = parsedDoubleTerms.getBuckets();
for (Terms.Bucket bucket : buckets) {
System.out.println(bucket.getKey()+" "+bucket.getDocCount());
}
}
查询结果:
3.3.3求出价格最大的值
@Test
public void testAggsFunction() throws IOException {
SearchRequest searchRequest = new SearchRequest("fruit");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder
.query(QueryBuilders.matchAllQuery())
// .aggregation(AggregationBuilders.sum("sum_price").field("price"))
// .aggregation(AggregationBuilders.avg("avg_price").field("price"))
.aggregation(AggregationBuilders.max("max_price").field("price"))
.size(0);
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
Aggregations aggregations = searchResponse.getAggregations();
// ParsedSum parsedSum = aggregations.get("sum_price");
// System.out.println(parsedSum.getValue());
// ParsedAvg parsedAvg = aggregations.get("avg_price");
// System.out.println(parsedAvg.getValue());
ParsedMax parsedMax = aggregations.get("max_price");
System.out.println(parsedMax.getValue());
}