Spring Boot 集成 Elasticsearch
原创转载请注明出处:https://www.cnblogs.com/agilestyle/p/15229906.html
Project Directory
Maven Dependency
<?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 http://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.3.12.RELEASE</version> <relativePath/> </parent> <groupId>org.fool.es</groupId> <artifactId>hello-spring-data-es</artifactId> <version>1.0-SNAPSHOT</version> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> </dependencies> </project>
application.properties
server.port=8080 logging.level.org.fool.es=debug elasticsearch.host=127.0.0.1 elasticsearch.port=9200
SRC
Application.java
package org.fool.es; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
ElasticsearchConfig.java
package org.fool.es.config; import lombok.Data; import lombok.EqualsAndHashCode; import org.apache.http.HttpHost; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestHighLevelClient; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration; @ConfigurationProperties(prefix = "elasticsearch") @Configuration @Data @EqualsAndHashCode(callSuper = true) public class ElasticsearchConfig extends AbstractElasticsearchConfiguration { private String host; private Integer port; @Override public RestHighLevelClient elasticsearchClient() { return new RestHighLevelClient(RestClient.builder(new HttpHost(host, port))); } }
使用 ElasticsearchRepository 进行通用的 CRUD
Product.java
package org.fool.es.index; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; 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; @Data @NoArgsConstructor @AllArgsConstructor @Document(indexName = "product", shards = 1, replicas = 1) public class Product { @Id private Long id; @Field(type = FieldType.Text, analyzer = "ik_max_word") private String title; @Field(type = FieldType.Keyword) private String category; @Field(type = FieldType.Double) private Double price; @Field(type = FieldType.Keyword, index = false) private String imageUrl; }
ProductDAO.java
package org.fool.es.dao; import org.fool.es.index.Product; import org.springframework.data.domain.Pageable; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; import org.springframework.stereotype.Repository; import java.util.List; @Repository public interface ProductDAO extends ElasticsearchRepository<Product, Long> { List<Product> findByTitle(String title); List<Product> findByTitle(String title, Pageable pageable); List<Product> findByTitleAndCategory(String title, String category); List<Product> findByTitleOrCategory(String title, String category); }
SpringDataESTest.java
package org.fool.es.test; import org.fool.es.dao.ProductDAO; import org.fool.es.index.Product; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.test.context.junit4.SpringRunner; import java.util.ArrayList; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest public class SpringDataESTest { @Autowired private ProductDAO productDAO; ...... }
insert
@Test public void testInsert() { Product product = new Product(); product.setId(1001L); product.setTitle("iPhone X"); product.setCategory("mobile"); product.setPrice(6999.0); product.setImageUrl("http://www.apple.com/iPhone.jpg"); productDAO.save(product); }
update
@Test public void testUpdate() { Product product = new Product(); product.setId(1001L); product.setTitle("iPhone X Max"); product.setCategory("mobile"); product.setPrice(8999.0); product.setImageUrl("http://www.apple.com/iPhone.jpg"); productDAO.save(product); }
delete
@Test public void testDelete() { Product product = new Product(); product.setId(1001L); productDAO.delete(product); }
batchInsert
@Test public void testBatchInsert() { List<Product> productList = new ArrayList<>(); for (int i = 0; i < 10; i++) { Product product = new Product(); product.setId((long) i); product.setTitle("iPhone " + i); product.setCategory("mobile"); product.setPrice(6999.0 + i); product.setImageUrl("http://www.apple.com/iPhone.jpg"); productList.add(product); } productDAO.saveAll(productList); }
findById
@Test public void testFindById() { productDAO.findById(1001L).ifPresent(System.out::println); }
findAll
@Test public void testFindAll() { productDAO.findAll().forEach(System.out::println); }
findByPageable
@Test public void findByPageable() { Sort sort = Sort.by(Sort.Direction.DESC, "id"); int currentPage = 0; int pageSize = 5; PageRequest pageRequest = PageRequest.of(currentPage, pageSize, sort); Page<Product> results = productDAO.findAll(pageRequest); System.out.println(results.getTotalPages()); System.out.println(results.getSize()); System.out.println(results.getNumber()); results.getContent().forEach(System.out::println); }
findByTitle
@Test public void testFindByTitle() { productDAO.findByTitle("iPhone 8").forEach(System.out::println); }
findByTitleWithPagination
@Test public void testFindByTitleWithPagination() { productDAO.findByTitle("iPhone", PageRequest.of(0, 5)).forEach(System.out::println); }
findByTitleOrCategory
@Test public void testFindByTitleOrCategory() { productDAO.findByTitleOrCategory("iPhone", "mobile").forEach(System.out::println); }
findByTitleAndCategory
@Test public void testFindByTitleAndCategory() { productDAO.findByTitleAndCategory("iPhone", "pad").forEach(System.out::println); }
使用 NativeSearchQuery 进行复杂查询
User.java
package org.fool.es.index; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; 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; @Data @NoArgsConstructor @AllArgsConstructor @Document(indexName = "user", shards = 1, replicas = 1) public class User { @Id private Long id; @Field(type = FieldType.Text, analyzer = "ik_max_word") private String name; @Field(type = FieldType.Keyword) private String sex; @Field(type = FieldType.Integer) private Integer age; @Field(type = FieldType.Text, analyzer = "ik_max_word") private String address; }
UserDAO.java
package org.fool.es.dao; import org.fool.es.index.User; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; import org.springframework.stereotype.Repository; @Repository public interface UserDAO extends ElasticsearchRepository<User, Long> { }
SpringESNativeSearchQueryTest.java
package org.fool.es.test; import org.elasticsearch.common.unit.Fuzziness; import org.elasticsearch.index.query.MatchAllQueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.aggregations.AggregationBuilders; import org.elasticsearch.search.aggregations.Aggregations; import org.elasticsearch.search.aggregations.bucket.terms.ParsedLongTerms; import org.elasticsearch.search.aggregations.bucket.terms.Terms; import org.elasticsearch.search.aggregations.metrics.ParsedMax; import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder; import org.elasticsearch.search.sort.SortBuilders; import org.elasticsearch.search.sort.SortOrder; import org.fool.es.dao.UserDAO; import org.fool.es.index.User; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.domain.PageRequest; import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; import org.springframework.data.elasticsearch.core.SearchHit; import org.springframework.data.elasticsearch.core.SearchHits; import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.data.elasticsearch.core.query.SourceFilter; import org.springframework.test.context.junit4.SpringRunner; import java.util.ArrayList; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest public class SpringESNativeSearchQueryTest { @Autowired private UserDAO userDAO; @Autowired private ElasticsearchRestTemplate elasticsearchRestTemplate; @Test public void testBatchInsert() throws Exception { List<User> recordList = new ArrayList<>(); recordList.add(new User(1001L, "caocao", "male", 10, "shanghai")); recordList.add(new User(1002L, "liubei", "male", 20, "beijing")); recordList.add(new User(1003L, "sunquan", "male", 30, "shenzhen")); recordList.add(new User(1004L, "guanyu", "male", 40, "guangzhou")); recordList.add(new User(1005L, "zhangfei", "male", 40, "shanghai")); recordList.add(new User(1006L, "zhaoyun", "male", 50, "beijing")); recordList.add(new User(1007L, "caocao2", "female", 50, "chengdu")); userDAO.saveAll(recordList); } @Test public void testDelete() { userDAO.deleteAll(); } ...... }
Note:
@Autowired private ElasticsearchRestTemplate elasticsearchRestTemplate;
queryAll
@Test public void testQueryAll() { NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder() .withQuery(new MatchAllQueryBuilder()) .build(); SearchHits<User> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, User.class); long count = searchHits.getTotalHits(); System.out.println(count); List<SearchHit<User>> list = searchHits.getSearchHits(); for (SearchHit<User> record : list) { System.out.println(record.getContent()); } }
queryString
@Test public void testQueryString() { NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder() // query field address .withQuery(QueryBuilders.queryStringQuery("shanghai").defaultField("address")) // query all field //.withQuery(QueryBuilders.queryStringQuery("shanghai")) // query field name, address //.withQuery(QueryBuilders.queryStringQuery("shanghai").field("name").field("address")) .build(); SearchHits<User> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, User.class); long count = searchHits.getTotalHits(); System.out.println(count); List<SearchHit<User>> list = searchHits.getSearchHits(); for (SearchHit<User> record : list) { System.out.println(record.getContent()); } }
queryTerm
@Test public void testQueryTerm() { NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder() .withQuery(QueryBuilders.termQuery("name", "caocao")) .build(); SearchHits<User> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, User.class); long count = searchHits.getTotalHits(); System.out.println(count); List<SearchHit<User>> list = searchHits.getSearchHits(); for (SearchHit<User> record : list) { System.out.println(record.getContent()); } }
queryPagination
@Test public void testQueryPagination() { NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder() .withQuery(QueryBuilders.matchAllQuery()) .withPageable(PageRequest.of(0, 5)) .build(); SearchHits<User> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, User.class); long count = searchHits.getTotalHits(); System.out.println(count); List<SearchHit<User>> list = searchHits.getSearchHits(); for (SearchHit<User> record : list) { System.out.println(record.getContent()); } }
querySort
@Test public void testQuerySort() { NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder() .withQuery(QueryBuilders.matchAllQuery()) .withPageable(PageRequest.of(0, 5)) .withSort(SortBuilders.fieldSort("id").order(SortOrder.DESC)) .build(); SearchHits<User> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, User.class); long count = searchHits.getTotalHits(); System.out.println(count); List<SearchHit<User>> list = searchHits.getSearchHits(); for (SearchHit<User> record : list) { System.out.println(record.getContent()); } }
queryFilter
@Test public void testQueryFilter() { NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder() .withQuery(QueryBuilders.matchAllQuery()) .withPageable(PageRequest.of(0, 5)) .withSourceFilter(new SourceFilter() { @Override public String[] getIncludes() { return new String[]{"name"}; } @Override public String[] getExcludes() { return new String[]{}; } }).build(); SearchHits<User> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, User.class); long count = searchHits.getTotalHits(); System.out.println(count); List<SearchHit<User>> list = searchHits.getSearchHits(); for (SearchHit<User> record : list) { System.out.println(record.getContent()); } }
queryBool
@Test public void testQueryBool() { // or //NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder() // .withQuery(QueryBuilders.boolQuery() // .should(QueryBuilders.termQuery("age", 30)) // .should(QueryBuilders.termQuery("sex", "female"))) // .build(); // and NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder() .withQuery(QueryBuilders.boolQuery() .must(QueryBuilders.termQuery("age", 30)) .must(QueryBuilders.termQuery("sex", "male"))) .build(); SearchHits<User> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, User.class); long count = searchHits.getTotalHits(); System.out.println(count); List<SearchHit<User>> list = searchHits.getSearchHits(); for (SearchHit<User> record : list) { System.out.println(record.getContent()); } }
queryRange
@Test public void testQueryRange() { NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder() .withQuery(QueryBuilders.rangeQuery("age").gte(30).lte(50)) .build(); SearchHits<User> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, User.class); long count = searchHits.getTotalHits(); System.out.println(count); List<SearchHit<User>> list = searchHits.getSearchHits(); for (SearchHit<User> record : list) { System.out.println(record.getContent()); } }
queryFuzzy
@Test public void testQueryFuzzy() { NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder() .withQuery(QueryBuilders.fuzzyQuery("name", "caocao").fuzziness(Fuzziness.ONE)) .build(); SearchHits<User> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, User.class); long count = searchHits.getTotalHits(); System.out.println(count); List<SearchHit<User>> list = searchHits.getSearchHits(); for (SearchHit<User> record : list) { System.out.println(record.getContent()); } }
queryHighlight
@Test public void testQueryHighlight() { NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder() .withQuery(QueryBuilders.termQuery("name", "caocao")) .withHighlightFields(new HighlightBuilder.Field("name").preTags("<font color='red'>").postTags("</font>")) .build(); SearchHits<User> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, User.class); long count = searchHits.getTotalHits(); System.out.println(count); List<SearchHit<User>> list = searchHits.getSearchHits(); for (SearchHit<User> record : list) { System.out.println(record.getContent()); System.out.println(record.getHighlightFields()); } }
queryAggregation
@Test public void testQueryAggregation() { NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder() .addAggregation(AggregationBuilders.max("maxAge").field("age")) .build(); SearchHits<User> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, User.class); long count = searchHits.getTotalHits(); System.out.println(count); Aggregations aggregations = searchHits.getAggregations(); assert aggregations != null; ParsedMax terms = aggregations.get("maxAge"); System.out.println(terms.getValue()); }
queryGroup
@Test public void testQueryGroup() { NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder() .addAggregation(AggregationBuilders.terms("ageGroup").field("age")) .build(); SearchHits<User> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, User.class); long count = searchHits.getTotalHits(); System.out.println(count); Aggregations aggregations = searchHits.getAggregations(); assert aggregations != null; ParsedLongTerms terms = aggregations.get("ageGroup"); List<? extends Terms.Bucket> buckets = terms.getBuckets(); for (Terms.Bucket bucket : buckets) { System.out.println(bucket.getKey() + ":" + bucket.getDocCount()); } }
Reference
欢迎点赞关注和收藏
强者自救 圣者渡人