1、Elasticsearch安装包下载
官网下载:https://www.elastic.co/cn/downloads/past-releases#elasticsearch
mac版本:elasticsearch-7.6.0
2、解压、配置
/elasticsearch-7.6.0/config/elasticsearch.yml文件增加配置
# 日志路径
path.logs: /xxx/xxx
xpack.ml.enabled: false
bin目录下启动
./elasticsearch
3、spring boot结合Elasticsearch
pom.xml文件,spring boot依赖冲突,需要使用正确ES版本
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.java</groupId>
<artifactId>java</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>java</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
<!-- 启动时不扫描测试类 -->
<skipTests>true</skipTests>
<!-- 指定elasticsearch版本 -->
<elasticsearch.version>7.15.2</elasticsearch.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.7</version>
</dependency>
<!-- mysql-->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.33</version>
</dependency>
<!-- elasticsearch-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
<version>2.6.4</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>4.3.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.28</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.7.18</version>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
4、配置ElasticsearchConfig
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 ElasticsearchConfig {
@Bean(destroyMethod = "close")
public RestHighLevelClient restHighLevelClient() {
RestHighLevelClient client = new RestHighLevelClient(
// 可以配置多个
RestClient.builder(
new HttpHost("127.0.0.1", 9200, "http")
// , new HttpHost("127.0.0.1", 9201, "http")
));
return client;
}
}
5、实体类
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.DateFormat;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import java.util.Date;
@Data
@Document(indexName = "blog")
public class Blog {
//此项作为id,不会写到_source里边。
@Id
private Long blogId;
@Field(name = "title", type = FieldType.Text)
private String title;
}
6、继承ElasticsearchRepository方法
import com.java.dao.es.Blog;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
public interface BlogRepository extends ElasticsearchRepository<Blog, Long> {
}
7、ES方法详情
RestHighLevelClient
RestHighLevelClient 是 Elasticsearch 官方提供的 Java High Level REST Client 的一部分,用于在 Java 应用程序中与 Elasticsearch 集群进行交互。这个客户端提供了比低级 REST 客户端更高级别的抽象,使得与 Elasticsearch 的交互更加简单和直观。
RestHighLevelClient 提供了多种方法来执行不同的操作,如索引文档、搜索文档、更新文档、删除文档等。以下是一些常用的 RestHighLevelClient 方法及其用途的概述:
索引文档
index(IndexRequest request, RequestOptions options):将一个文档索引到指定的索引中。
搜索文档
search(SearchRequest searchRequest, RequestOptions options):执行一个搜索请求并返回 SearchResponse。
searchAsync(SearchRequest searchRequest, RequestOptions options, ActionListener<SearchResponse> listener):异步执行搜索请求。
获取文档
get(GetRequest getRequest, RequestOptions options):从索引中获取一个文档。
更新文档
update(UpdateRequest request, RequestOptions options):更新索引中的文档。
删除文档
delete(DeleteRequest request, RequestOptions options):从索引中删除一个文档。
创建索引
虽然 RestHighLevelClient 没有直接的方法来创建索引(因为索引的创建通常是通过发送一个包含索引定义的 PUT 请求到 /<index> 端点来完成的),但你可以使用 indices().create(CreateIndexRequest request, RequestOptions options) 方法,这是通过 IndicesClient 接口提供的,而 RestHighLevelClient 提供了对它的访问。
删除索引
同样,RestHighLevelClient 没有直接的方法来删除索引,但你可以通过 indices().delete(DeleteIndexRequest request, RequestOptions options) 方法来做到这一点。
其他操作
indices(): 返回 IndicesClient 实例,用于执行与索引相关的操作,如获取索引信息、删除索引、创建索引等。
cluster(): 返回 ClusterClient 实例,用于执行与集群相关的操作,如获取集群健康状态、节点信息等。
QueryBuilders方法
QueryBuilders方法
/**
* 匹配所有文档(Match All Query)
* QueryBuilders.matchAllQuery();
*
* 匹配查询(Match Query)
* fieldName 字段中搜索包含 textToSearch 的文档。
* QueryBuilders.matchQuery("fieldName", "textToSearch");
*
* 布尔查询(Boolean Query)
* 布尔查询允许你组合多个查询子句,如 must(必须匹配)、should(应该匹配,但不是必须的)、must_not(必须不匹配)。
* QueryBuilders.boolQuery()
* .must(QueryBuilders.matchQuery("field1", "value1"))
* .should(QueryBuilders.matchQuery("field2", "value2"))
* .mustNot(QueryBuilders.matchQuery("field3", "value3"));
*
* 范围查询(Range Query)
* 这会找到 age 字段值在10(包含)到20(不包含)之间的文档。
* QueryBuilders.rangeQuery("age")
* .from(10)
* .to(20)
* .includeLower(true)
* .includeUpper(false);
*
* 术语查询(Term Query)
* 术语查询用于精确值匹配,不分析查询字符串。
* QueryBuilders.termQuery("status", "active");
*
* 前缀查询(Prefix Query)
* 这会在 fieldName 字段中搜索以 prefixText 开头的文档。
* QueryBuilders.prefixQuery("fieldName", "prefixText");
*
* 模糊查询(Fuzzy Query)
* 这会在 fieldName 字段中搜索与 textToSearch 相似的文档,fuzziness 参数定义了相似度级别。
* QueryBuilders.fuzzyQuery("fieldName", "textToSearch")
* .fuzziness(Fuzziness.TWO);
*
* 通配符查询(Wildcard Query)
* 这会在 fieldName 字段中搜索以 text 开头的文档。
* QueryBuilders.wildcardQuery("fieldName", "text*");
*
* 嵌套查询(Nested Query) 对于嵌套对象,你需要使用 nestedQuery。
* 这会在嵌套文档 path_to_nested_doc 中搜索 field 字段值为 value 的文档,并指定了评分模式为 Avg。
* QueryBuilders.nestedQuery(
* "path_to_nested_doc",
* QueryBuilders.matchQuery("path_to_nested_doc.field", "value"),
* ScoreMode.Avg
* );
*
*/
8、 ES示例
import com.java.dao.es.Blog;
import com.java.mapper.es.BlogRepository;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Slf4j
@RestController
@RequestMapping("/es")
public class EsCrudController {
@Autowired
private BlogRepository blogRepository;
@Autowired
private RestHighLevelClient restHighLevelClient;
@GetMapping("/searchQueryBuilders")
public Object searchQueryBuilders() throws IOException {
SearchRequest searchRequest = new SearchRequest("blog");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
/**
* 匹配所有文档(Match All Query)
* QueryBuilders.matchAllQuery();
*
* 匹配查询(Match Query)
* fieldName 字段中搜索包含 textToSearch 的文档。
* QueryBuilders.matchQuery("fieldName", "textToSearch");
*
* 布尔查询(Boolean Query)
* 布尔查询允许你组合多个查询子句,如 must(必须匹配)、should(应该匹配,但不是必须的)、must_not(必须不匹配)。
* QueryBuilders.boolQuery()
* .must(QueryBuilders.matchQuery("field1", "value1"))
* .should(QueryBuilders.matchQuery("field2", "value2"))
* .mustNot(QueryBuilders.matchQuery("field3", "value3"));
*
* 范围查询(Range Query)
* 这会找到 age 字段值在10(包含)到20(不包含)之间的文档。
* QueryBuilders.rangeQuery("age")
* .from(10)
* .to(20)
* .includeLower(true)
* .includeUpper(false);
*
* 术语查询(Term Query)
* 术语查询用于精确值匹配,不分析查询字符串。
* QueryBuilders.termQuery("status", "active");
*
* 前缀查询(Prefix Query)
* 这会在 fieldName 字段中搜索以 prefixText 开头的文档。
* QueryBuilders.prefixQuery("fieldName", "prefixText");
*
* 模糊查询(Fuzzy Query)
* 这会在 fieldName 字段中搜索与 textToSearch 相似的文档,fuzziness 参数定义了相似度级别。
* QueryBuilders.fuzzyQuery("fieldName", "textToSearch")
* .fuzziness(Fuzziness.TWO);
*
* 通配符查询(Wildcard Query)
* 这会在 fieldName 字段中搜索以 text 开头的文档。
* QueryBuilders.wildcardQuery("fieldName", "text*");
*
* 嵌套查询(Nested Query) 对于嵌套对象,你需要使用 nestedQuery。
* 这会在嵌套文档 path_to_nested_doc 中搜索 field 字段值为 value 的文档,并指定了评分模式为 Avg。
* QueryBuilders.nestedQuery(
* "path_to_nested_doc",
* QueryBuilders.matchQuery("path_to_nested_doc.field", "value"),
* ScoreMode.Avg
* );
*
*/
RangeQueryBuilder query = QueryBuilders.rangeQuery("blogId").from(10).to(13).includeLower(true).includeUpper(true);
searchSourceBuilder.query(query);
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
List<String> results = new ArrayList<>();
for (SearchHit hit : hits) {
String sourceAsString = hit.getSourceAsString();
results.add(sourceAsString);
}
return results;
}
@GetMapping("/searchSelect")
public Object searchSelect() throws IOException {
SearchRequest searchRequest = new SearchRequest("blog");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 构建 Term Query
MatchPhraseQueryBuilder query = QueryBuilders.matchPhraseQuery("title", "Spring Data ElasticSearch学习教程1");
searchSourceBuilder.query(query);
searchRequest.source(searchSourceBuilder);
// 发送请求并处理响应
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
List<String> results = new ArrayList<>();
for (SearchHit hit : hits) {
String jsonString = hit.getSourceAsString();
// 这里你可以使用Jackson或其他JSON库来将jsonString转换为YourEntity对象
// 或者,如果你已经配置了Spring Data Elasticsearch的实体映射,你可能不需要这样做
// 这里仅作为示例,我们直接添加jsonString到结果列表中
log.info("获取数据:" + jsonString);
results.add(jsonString);
// 实际上,你可能需要这样做:YourEntity entity = objectMapper.readValue(jsonString, YourEntity.class);
}
return results;
}
/**
* 添加单个文档
*
* @return
*/
@GetMapping("addDocument")
public Blog addDocument() {
Long id = 1L;
Blog blog = new Blog();
blog.setBlogId(id);
blog.setTitle("Spring Data ElasticSearch学习教程" + id);
blog.setContent("这是添加单个文档的实例" + id);
blog.setAuthor("Tony");
blog.setCategory("ElasticSearch");
blog.setCreateTime(new Date());
blog.setStatus(1);
blog.setSerialNum(id.toString());
return blogRepository.save(blog);
}
/**
* 添加多个文档
*
* @param count
* @return
*/
@GetMapping("/addDocuments/{count}")
public Object addDocuments(@PathVariable Integer count) {
long startTime = System.currentTimeMillis();
List<Blog> blogs = new ArrayList<>();
for (int i = 1; i <= count; i++) {
Long id = (long) i;
Blog blog = new Blog();
blog.setBlogId(id);
blog.setTitle("Spring Data ElasticSearch学习教程" + id);
blog.setContent("这是添加单个文档的实例" + id);
blog.setAuthor("Tony");
blog.setCategory("ElasticSearch");
blog.setCreateTime(new Date());
blog.setStatus(1);
blog.setSerialNum(id.toString());
blogs.add(blog);
}
Iterable<Blog> saveAll = blogRepository.saveAll(blogs);
long endTime = System.currentTimeMillis();
log.info("执行时间:" + (endTime - startTime) / 1000 + " 秒");
return saveAll
;
}
/**
* 修改单个文档
* 跟新增是同一个方法。若id已存在,则修改。
* 无法只修改某个字段,只能覆盖所有字段。若某个字段没有值,则会写入null。
*
* @return 成功写入的数据
*/
@PostMapping("editDocument")
public Blog editDocument() {
Long id = 1L;
Blog blog = new Blog();
blog.setBlogId(id);
blog.setTitle("Spring Data ElasticSearch学习教程" + id);
blog.setContent("这是修改单个文档的实例" + id);
// blog.setAuthor("Tony");
// blog.setCategory("ElasticSearch");
// blog.setCreateTime(new Date());
// blog.setStatus(1);
// blog.setSerialNum(id.toString());
return blogRepository.save(blog);
}
/**
* 查找单个文档
*
* @param id
* @return
*/
@GetMapping("findById/{id}")
public Blog findById(@PathVariable Long id) {
return blogRepository.findById(id).get();
}
/**
* 删除单个文档
*
* @param id
* @return
*/
@GetMapping("deleteDocument/{id}")
public String deleteDocument(@PathVariable Long id) {
blogRepository.deleteById(id);
return "success";
}
/**
* 删除所有文档
*
* @return
*/
@GetMapping("deleteDocumentAll")
public String deleteDocumentAll() {
blogRepository.deleteAll();
return "success";
}
/**
* 查询所有文档
*/
@GetMapping("/findAll")
public Object findAll(){
return blogRepository.findAll();
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。