暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Spring Boot 集成 Elasticsearch

TechStyle 2021-09-08
588

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

https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#elasticsearch.repositories




泰克风格 只讲干货 不弄玄虚

文章转载自TechStyle,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论