我看到希望,哪怕只有微小的一束光,我也会拼尽全力去寻找

上一章简单介绍了 ES的Java API 操作(五), 如果没有看过,请观看上一章

一. 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

如果已经存在了索引,则不会自动创建.

SpringBoot 整合 ES (六)_spring

二. 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(">>> 创建生成单个文档成功");
	}

SpringBoot 整合 ES (六)_spring_02

二.二 根据 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(">>> 更新文档成功");
	}

SpringBoot 整合 ES (六)_elasticsearch_03

二.四 根据 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(">>>批量添加文档成功");
	}

SpringBoot 整合 ES (六)_spring_04

二.六 全部查询文档

/**
	 * 批量查询文档
	 */
	@Test
	public void findAllTest() {
		Iterable<Product> allList = productRepository.findAll();
		allList.forEach(
				n -> log.info("文档:{}", n)
		);
	}

SpringBoot 整合 ES (六)_spring_05

二.七 根据 id 批量查询记录

/**
	 * 根据id 集合批量查询记录
	 */
	@Test
	public void findAllByIdListTest() {
		Iterable<Product> allList = productRepository.findAllById(Arrays.asList(1, 5, 6));
		allList.forEach(
				n -> log.info("文档:{}", n)
		);
	}

SpringBoot 整合 ES (六)_Test_06

二.八 批量更新

/**
	 * 批量更新, 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();
	}

SpringBoot 整合 ES (六)_spring_07

二.九 批量删除

/**
	 * 批量删除
	 */
	@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());
					}
				}
		);
	}

SpringBoot 整合 ES (六)_Test_08

三.二 根据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);
	}

SpringBoot 整合 ES (六)_spring_09

三.三 分页查询

/**
	 * 分页查询
	 * 从 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);
		
	}

SpringBoot 整合 ES (六)_elasticsearch_10

三.四 分页排序查询

/**
	 * 分页排序
	 */
	@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);
	}

SpringBoot 整合 ES (六)_Test_11

三.五 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);
	}

SpringBoot 整合 ES (六)_Test_12

三.六 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);
	}

SpringBoot 整合 ES (六)_elasticsearch_13

三.七 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);
	}

故意将 学习 变成 学哈

SpringBoot 整合 ES (六)_spring_14

三.八 高亮展示

@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);
		
	}

SpringBoot 整合 ES (六)_Test_15

三.九 组合条件查询

@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);
	}

SpringBoot 整合 ES (六)_spring_16

本章节的代码放置在 github 上:

https://github.com/yuejianli/springboot/tree/develop/SpringBoot_ES2

谢谢您的观看,如果喜欢,请关注我,再次感谢 !!!