我看到希望,哪怕只有微小的一束光,我也会拼尽全力去寻找
上一章简单介绍了 SpringBoot 整合 RabbitMQ (四十一), 如果没有看过,请观看上一章
ES 相应的教程,可以看老蝴蝶之前写的文章: https://blog.csdn.net/yjltx1234csdn/category_12277559.html
一. SpringBoot 整合ES
我们上一章节使用 Java API, 发现操作是很复杂的, 如果可以像操作 jpa, redis 一样, 提供对应的 JpaRestTemplate ,RedisRestTemplate 操作就好了.
其实也提供了相应的信息.
一. 一. pom.xml 引入依赖
<!--引入 spring-data-elasticsearch-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
一.二. 配置RestHighLevelClient
一.二.一. application.yml 配置 host 和port
elasticsearch:
host: 127.0.0.1
port: 9200
一.二.一 配置 ES 的 Config
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration;
import org.springframework.stereotype.Component;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 配置 ES
*
* @author yuejianli
* @date 2022-08-18
*/
@Component
@ConfigurationProperties("elasticsearch")
@Data
public class EsConfig extends AbstractElasticsearchConfiguration {
private String host;
private Integer port;
@Override
public RestHighLevelClient elasticsearchClient() {
RestClientBuilder restClientBuilder = RestClient.builder(new HttpHost(host, port));
return new RestHighLevelClient(restClientBuilder);
}
}
一.三 配置相应的实体 Product
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;
import lombok.Data;
/**
* 商品
*
* @author yuejianli
* @date 2022-08-18
*/
@Data
@Document(indexName = "product")
public class Product {
@Id
private Integer id;
@Field(type = FieldType.Text, analyzer = "ik_max_word")
private String title;
@Field(type = FieldType.Text, analyzer = "ik_max_word")
private String author;
@Field(type = FieldType.Keyword)
private String category;
@Field(type = FieldType.Double)
private Double price;
@Field(type = FieldType.Keyword, index = false)
private String image;
}
@Document, 指定索引名
@Id, 必须要有 id, 是全局唯一标识, 等同于 es 中的 _id
@Field 标识属性,type 指定 字段数据类型, analyzer 分词器类型, index 是否是索引, 默认为索引.
Keyword 短语, 不进行分词。
一.四 创建对应实体的 Repository
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;
/**
* 用途描述
*
* @author yuejianli
* @date 2022-08-18
*/
@Repository
public interface ProductRepository extends ElasticsearchRepository<Product, Integer> {
}
是不是很像 JPA 了 ?
一.五 执行,测试整合验证
@Test
public void createIndexTest() {
log.info(">>>> 创建索引成功");
}
实体 Product, 标记了 Document 索引, 如果没有索引的话,会自动创建索引 product
如果已经存在了索引,则不会自动创建.
二. Repository 文档操作
@Resource
private ProductRepository productRepository;
二.一 新增文档
/**
* 新增文档操作
*/
@Test
public void addTest() {
Product product = new Product();
product.setId(1);
product.setTitle("两个蝴蝶飞学习 ES");
product.setCategory("图书");
product.setPrice(40.0d);
product.setImage("https://www.yueshushu.top");
productRepository.save(product);
log.info(">>> 创建生成单个文档成功");
}
二.二 根据 id 查询文档
/**
* 根据id 查询文档
*/
@Test
public void searchByIdTest() {
Optional<Product> productOptional = productRepository.findById(1);
if (productOptional.isPresent()) {
Product product = productOptional.get();
log.info(">>> 查询文档信息:{}", product);
} else {
log.info(">>> 没有此文档");
}
}
2023-04-10 13:42:03.870 INFO 41120 --- [ main] top.yueshushu.DocumentTest : >>> 查询文档信息:Product(id=1, title=两个蝴蝶飞学习 ES, author=null, category=图书, price=40.0, image=https://www.yueshushu.top)
二.三 根据文档
/**
* 更新文档
*/
@Test
public void updateByIdTest() {
// 更新文档
Optional<Product> productOptional = productRepository.findById(1);
if (!productOptional.isPresent()) {
return;
}
Product product = productOptional.get();
product.setPrice(38.0d);
product.setCategory("Java");
//进行更新
productRepository.save(product);
log.info(">>> 更新文档成功");
}
二.四 根据 id 删除文档
/**
* 根据id 删除文档
*/
@Test
public void deleteByIdTest() {
productRepository.deleteById(1);
log.info(">>> 删除文档成功");
searchByIdTest();
}
执行后,文档会删除。
二.五 批量添加文档
/**
* 批量添加文档
*/
@Test
public void batchInsertTest() {
List<Product> list = new ArrayList<>();
for (int i = 0; i <= 10; i++) {
Product product = new Product();
product.setId(i + 1);
product.setTitle("两个蝴蝶飞学习 ES" + i);
product.setCategory("图书");
product.setPrice(40.0d * i);
product.setImage("https://www.yueshushu.top");
list.add(product);
}
//批量添加
productRepository.saveAll(list);
log.info(">>>批量添加文档成功");
}
二.六 全部查询文档
/**
* 批量查询文档
*/
@Test
public void findAllTest() {
Iterable<Product> allList = productRepository.findAll();
allList.forEach(
n -> log.info("文档:{}", n)
);
}
二.七 根据 id 批量查询记录
/**
* 根据id 集合批量查询记录
*/
@Test
public void findAllByIdListTest() {
Iterable<Product> allList = productRepository.findAllById(Arrays.asList(1, 5, 6));
allList.forEach(
n -> log.info("文档:{}", n)
);
}
二.八 批量更新
/**
* 批量更新, id一样,则更新。没有id,则添加。
*/
@Test
public void batchUpdateTest() {
Iterable<Product> allList = productRepository.findAllById(Arrays.asList(1, 5, 6));
allList.forEach(
n -> {
n.setPrice(10.d);
n.setImage("http://被修改了");
}
);
List<Product> list = new ArrayList<>();
for (int i = 20; i <= 22; i++) {
Product product = new Product();
product.setId(i + 1);
product.setTitle("两个蝴蝶飞学习 Java " + i);
product.setCategory("图书");
product.setPrice(40.0d * i);
product.setImage("http://url1");
list.add(product);
}
ArrayList<Product> findALlList = Lists.newArrayList(allList);
list.addAll(findALlList);
//批量处理
productRepository.saveAll(list);
log.info(">>>>批量修改成功");
findAllTest();
}
二.九 批量删除
/**
* 批量删除
*/
@Test
public void batchDeleteTest() {
Iterable<Product> allList = productRepository.findAllById(Arrays.asList(1, 2, 3));
ArrayList<Product> findALlList = Lists.newArrayList(allList);
productRepository.deleteAll(findALlList);
log.info(">>>> 批量删除成功");
findAllTest();
}
再次查询时,会查询不到 id为 1,2,3 的记录信息
三. 查询
除了全部查询, 或者 根据id 查询, 一般会使用 ElasticsearchRestTemplate 进行查询
@Resource
private ElasticsearchRestTemplate elasticsearchRestTemplate;
三.一 全部查询
/**
* 全部查询
*/
@Test
public void findAllTest() {
NativeSearchQuery nativeSearchQuery =
new NativeSearchQuery(QueryBuilders.matchAllQuery());
SearchHits<Product> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, Product.class);
showInfo(searchHits);
}
/**
* 展示信息
*/
public void showInfo(SearchHits<Product> searchResult) {
long totalHits = searchResult.getTotalHits();
log.info(">>> 总数:{}", totalHits);
List<SearchHit<Product>> searchHitList = searchResult.getSearchHits();
searchHitList.forEach(
n -> {
Product product = n.getContent();
log.info(">>> 输出信息:{}", product);
if (!CollectionUtils.isEmpty(n.getHighlightFields())){
log.info("高亮:{}", n.getHighlightFields());
}
}
);
}
三.二 根据id 查询
/**
* 一个简单的查询
* id =4
*/
@Test
public void simpleQueryTest() {
NativeSearchQuery nativeSearchQuery = new NativeSearchQuery(
QueryBuilders.termQuery("id", "4"));
SearchHits<Product> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, Product.class);
showInfo(searchHits);
}
三.三 分页查询
/**
* 分页查询
* 从 0开始
*/
@Test
public void pageTest() {
NativeSearchQuery nativeSearchQuery =
new NativeSearchQuery(QueryBuilders.matchAllQuery());
Pageable pageable = PageRequest.of(2, 4);
nativeSearchQuery.setPageable(pageable);
// 进行查询
SearchHits<Product> search = elasticsearchRestTemplate.search(nativeSearchQuery, Product.class);
showInfo(search);
}
三.四 分页排序查询
/**
* 分页排序
*/
@Test
public void sortTest() {
NativeSearchQuery nativeSearchQuery = new NativeSearchQuery(
QueryBuilders.matchAllQuery()
);
Sort sort = Sort.by(Sort.Order.desc("price"));
Pageable pageable = PageRequest.of(1, 4, sort);
nativeSearchQuery.setPageable(pageable);
SearchHits<Product> search = elasticsearchRestTemplate.search(nativeSearchQuery, Product.class);
showInfo(search);
}
三.五 bool 查询
/**
* bool 查询, 类型必须是图片, id不能为5.
* name 可以为
*/
@Test
public void boolTest() {
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(QueryBuilders.termQuery("category", "图书"));
boolQueryBuilder.mustNot(QueryBuilders.termQuery("id", 5));
boolQueryBuilder.should(QueryBuilders.termQuery("price", 360.0d));
NativeSearchQuery nativeSearchQuery = new NativeSearchQuery(boolQueryBuilder);
SearchHits<Product> search = elasticsearchRestTemplate.search(nativeSearchQuery, Product.class);
showInfo(search);
}
三.六 range 范围查询
@Test
public void rangeTest() {
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("price");
rangeQueryBuilder.gte(100.0);
rangeQueryBuilder.lte(300.0d);
NativeSearchQuery nativeSearchQuery = new NativeSearchQuery(rangeQueryBuilder);
SearchHits<Product> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, Product.class);
showInfo(searchHits);
}
三.七 like 查询
@Test
public void likeTest() {
FuzzyQueryBuilder fuzzyQueryBuilder = QueryBuilders.fuzzyQuery("title", "学哈");
fuzzyQueryBuilder.fuzziness(Fuzziness.ONE);
NativeSearchQuery nativeSearchQuery = new NativeSearchQuery(fuzzyQueryBuilder);
SearchHits<Product> search = elasticsearchRestTemplate.search(nativeSearchQuery, Product.class);
showInfo(search);
}
故意将 学习 变成 学哈
三.八 高亮展示
@Test
public void hightTest() {
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.preTags("<font color='red'>");
highlightBuilder.postTags("</font>");
highlightBuilder.field("title");
FuzzyQueryBuilder fuzzyQueryBuilder = QueryBuilders.fuzzyQuery("title", "学哈");
fuzzyQueryBuilder.fuzziness(Fuzziness.ONE);
NativeSearchQuery nativeSearchQuery = new NativeSearchQuery(fuzzyQueryBuilder, null, null, highlightBuilder, null);
SearchHits<Product> search = elasticsearchRestTemplate.search(nativeSearchQuery, Product.class);
showInfo(search);
}
三.九 组合条件查询
@Test
public void criteriaTest() {
// 条件查询
Criteria criteria = Criteria.where(new SimpleField("title")).contains("学习")
.or( new SimpleField("id")).greaterThan("5");
CriteriaQuery criteriaQuery = new CriteriaQuery(criteria);
SearchHits<Product> search = elasticsearchRestTemplate.search(criteriaQuery, Product.class);
showInfo(search);
}
本章节的代码放置在 github 上:
https://github.com/yuejianli/springboot/tree/develop/SpringBoot_ES2
谢谢您的观看,如果喜欢,请关注我,再次感谢 !!!
oduct.class);
showInfo(search);
}
[外链图片转存中...(img-P5D73Are-1681367811089)]
## 三.九 组合条件查询
~~~java
@Test
public void criteriaTest() {
// 条件查询
Criteria criteria = Criteria.where(new SimpleField("title")).contains("学习")
.or( new SimpleField("id")).greaterThan("5");
CriteriaQuery criteriaQuery = new CriteriaQuery(criteria);
SearchHits<Product> search = elasticsearchRestTemplate.search(criteriaQuery, Product.class);
showInfo(search);
}
[外链图片转存中…(img-tF7udgVf-1681367811089)]
本章节的代码放置在 github 上:
https://github.com/yuejianli/springboot/tree/develop/SpringBoot_ES2
谢谢您的观看,如果喜欢,请关注我,再次感谢 !!!