Merge branch 'eugenp:master' into master

This commit is contained in:
edizor
2023-01-20 16:10:28 +08:00
committed by GitHub
32 changed files with 797 additions and 137 deletions
@@ -6,17 +6,17 @@ import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.RestClients;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration;
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
@Configuration
@EnableElasticsearchRepositories(basePackages = "com.baeldung.spring.data.es.repository")
@ComponentScan(basePackages = { "com.baeldung.spring.data.es.service" })
public class Config {
public class Config extends AbstractElasticsearchConfiguration {
@Bean
RestHighLevelClient client() {
@Override
public RestHighLevelClient elasticsearchClient() {
ClientConfiguration clientConfiguration = ClientConfiguration.builder()
.connectedTo("localhost:9200")
.build();
@@ -24,9 +24,4 @@ public class Config {
return RestClients.create(clientConfiguration)
.rest();
}
@Bean
public ElasticsearchOperations elasticsearchTemplate() {
return new ElasticsearchRestTemplate(client());
}
}
@@ -22,7 +22,7 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
@@ -41,7 +41,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
public class ElasticSearchManualTest {
@Autowired
private ElasticsearchRestTemplate elasticsearchTemplate;
private ElasticsearchOperations elasticsearchOperations;
@Autowired
private ArticleRepository articleRepository;
@@ -117,7 +117,7 @@ public class ElasticSearchManualTest {
final Query searchQuery = new NativeSearchQueryBuilder().withFilter(regexpQuery("title", ".*data.*"))
.build();
final SearchHits<Article> articles = elasticsearchTemplate.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
final SearchHits<Article> articles = elasticsearchOperations.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
assertEquals(1, articles.getTotalHits());
}
@@ -126,7 +126,7 @@ public class ElasticSearchManualTest {
public void givenSavedDoc_whenTitleUpdated_thenCouldFindByUpdatedTitle() {
final Query searchQuery = new NativeSearchQueryBuilder().withQuery(fuzzyQuery("title", "serch"))
.build();
final SearchHits<Article> articles = elasticsearchTemplate.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
final SearchHits<Article> articles = elasticsearchOperations.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
assertEquals(1, articles.getTotalHits());
@@ -147,7 +147,7 @@ public class ElasticSearchManualTest {
final Query searchQuery = new NativeSearchQueryBuilder().withQuery(matchQuery("title", articleTitle).minimumShouldMatch("75%"))
.build();
final SearchHits<Article> articles = elasticsearchTemplate.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
final SearchHits<Article> articles = elasticsearchOperations.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
assertEquals(1, articles.getTotalHits());
final long count = articleRepository.count();
@@ -162,7 +162,7 @@ public class ElasticSearchManualTest {
public void givenSavedDoc_whenOneTermMatches_thenFindByTitle() {
final Query searchQuery = new NativeSearchQueryBuilder().withQuery(matchQuery("title", "Search engines").operator(AND))
.build();
final SearchHits<Article> articles = elasticsearchTemplate.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
final SearchHits<Article> articles = elasticsearchOperations.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
assertEquals(1, articles.getTotalHits());
}
}
@@ -39,7 +39,7 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
@@ -58,7 +58,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
public class ElasticSearchQueryManualTest {
@Autowired
private ElasticsearchRestTemplate elasticsearchTemplate;
private ElasticsearchOperations elasticsearchOperations;
@Autowired
private ArticleRepository articleRepository;
@@ -101,7 +101,7 @@ public class ElasticSearchQueryManualTest {
public void givenFullTitle_whenRunMatchQuery_thenDocIsFound() {
final NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchQuery("title", "Search engines").operator(Operator.AND))
.build();
final SearchHits<Article> articles = elasticsearchTemplate.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
final SearchHits<Article> articles = elasticsearchOperations.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
assertEquals(1, articles.getTotalHits());
}
@@ -110,7 +110,7 @@ public class ElasticSearchQueryManualTest {
final NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchQuery("title", "Engines Solutions"))
.build();
final SearchHits<Article> articles = elasticsearchTemplate.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
final SearchHits<Article> articles = elasticsearchOperations.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
assertEquals(1, articles.getTotalHits());
assertEquals("Search engines", articles.getSearchHit(0)
@@ -123,7 +123,7 @@ public class ElasticSearchQueryManualTest {
final NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchQuery("title", "elasticsearch data"))
.build();
final SearchHits<Article> articles = elasticsearchTemplate.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
final SearchHits<Article> articles = elasticsearchOperations.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
assertEquals(3, articles.getTotalHits());
}
@@ -133,14 +133,14 @@ public class ElasticSearchQueryManualTest {
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchQuery("title.verbatim", "Second Article About Elasticsearch"))
.build();
SearchHits<Article> articles = elasticsearchTemplate.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
SearchHits<Article> articles = elasticsearchOperations.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
assertEquals(1, articles.getTotalHits());
searchQuery = new NativeSearchQueryBuilder().withQuery(matchQuery("title.verbatim", "Second Article About"))
.build();
articles = elasticsearchTemplate.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
articles = elasticsearchOperations.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
assertEquals(0, articles.getTotalHits());
}
@@ -150,7 +150,7 @@ public class ElasticSearchQueryManualTest {
final NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(builder)
.build();
final SearchHits<Article> articles = elasticsearchTemplate.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
final SearchHits<Article> articles = elasticsearchOperations.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
assertEquals(2, articles.getTotalHits());
}
@@ -205,7 +205,7 @@ public class ElasticSearchQueryManualTest {
final NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchPhraseQuery("title", "spring elasticsearch").slop(1))
.build();
final SearchHits<Article> articles = elasticsearchTemplate.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
final SearchHits<Article> articles = elasticsearchOperations.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
assertEquals(1, articles.getTotalHits());
}
@@ -217,7 +217,7 @@ public class ElasticSearchQueryManualTest {
.prefixLength(3))
.build();
final SearchHits<Article> articles = elasticsearchTemplate.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
final SearchHits<Article> articles = elasticsearchOperations.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
assertEquals(1, articles.getTotalHits());
}
@@ -229,7 +229,7 @@ public class ElasticSearchQueryManualTest {
.type(MultiMatchQueryBuilder.Type.BEST_FIELDS))
.build();
final SearchHits<Article> articles = elasticsearchTemplate.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
final SearchHits<Article> articles = elasticsearchOperations.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
assertEquals(2, articles.getTotalHits());
}
@@ -241,7 +241,7 @@ public class ElasticSearchQueryManualTest {
final NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(builder)
.build();
final SearchHits<Article> articles = elasticsearchTemplate.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
final SearchHits<Article> articles = elasticsearchOperations.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
assertEquals(2, articles.getTotalHits());
}
@@ -0,0 +1,75 @@
package com.baeldung.spring.data.persistence.search;
import java.util.Objects;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String name;
private int score;
public Student() {
}
public Student(String name, int score) {
this.name = name;
this.score = score;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", score=" + score + "]";
}
@Override
public int hashCode() {
return Objects.hash(id, name, score);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
return id == other.id && Objects.equals(name, other.name) && score == other.score;
}
}
@@ -0,0 +1,16 @@
package com.baeldung.spring.data.persistence.search;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class StudentApplication {
private static final Logger log = LoggerFactory.getLogger(StudentApplication.class);
public static void main(String[] args) {
SpringApplication.run(StudentApplication.class, args);
}
}
@@ -0,0 +1,31 @@
package com.baeldung.spring.data.persistence.search;
import java.util.List;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface StudentRepository extends JpaRepository<Student, Long> {
Student findFirstByOrderByScoreDesc();
Student findFirstBy(Sort sort);
Student findFirstByNameLike(String name, Sort sort);
List<Student> findFirst3ByOrderByScoreDesc();
List<Student> findFirst2ByScoreBetween(int startScore, int endScore, Sort sort);
Student findTopByOrderByScoreDesc();
Student findTopBy(Sort sort);
Student findTopByNameLike(String name, Sort sort);
List<Student> findTop3ByOrderByScoreDesc();
List<Student> findTop2ByScoreBetween(int startScore, int endScore, Sort sort);
}
@@ -3,3 +3,4 @@ spring.datasource.username=sa
spring.datasource.password=sa
spring.jpa.properties.hibernate.globally_quoted_identifiers=true
logging.level.com.baeldung.spring.data.persistence.search=debug
@@ -0,0 +1,100 @@
package com.baeldung.spring.data.persistence.search;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Sort;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class StudentApplicationUnitTest {
@Autowired
private StudentRepository studentRepo;
private List<Student> students;
@Before
public void fillData() {
students = new ArrayList<>();
int count = 10;
Random r = new Random();
List<Integer> scores = r.ints(0, 101)
.distinct()
.limit(count)
.boxed()
.collect(Collectors.toList());
for (int i = 0; i < count; i++) {
Integer score = scores.get(i);
Student s = new Student("Student-" + i, score);
students.add(s);
}
studentRepo.saveAll(students);
Comparator<Student> c = Comparator.comparing(a -> a.getScore());
c = c.reversed();
students.sort(c);
}
@After
public void clearData() {
studentRepo.deleteAll();
}
@Test
public void givenStudentScores_whenMoreThanOne_thenFindFirst() {
Student student = studentRepo.findFirstByOrderByScoreDesc();
Student s = students.get(0);
assertEquals(student, s);
}
@Test
public void givenStudentScores_whenMoreThan3_thenFindFirstThree() {
List<Student> firstThree = studentRepo.findFirst3ByOrderByScoreDesc();
List<Student> sList = students.subList(0, 3);
assertArrayEquals(firstThree.toArray(), sList.toArray());
}
@Test
public void givenStudentScores_whenNameMatches_thenFindFirstStudent() {
String matchString = "3";
Student student = studentRepo.findFirstByNameLike("%" + matchString + "%", Sort.by("score")
.descending());
Student s = students.stream()
.filter(a -> a.getName()
.contains(matchString))
.findFirst()
.orElse(null);
assertEquals(student, s);
}
@Test
public void givenStudentScores_whenBetweenRange_thenFindFirstTwoStudents() {
List<Student> topTwoBetweenRange = studentRepo.findFirst2ByScoreBetween(50, 60, Sort.by("score")
.descending());
List<Student> _students = students.stream()
.filter(a -> a.getScore() >= 50 && a.getScore() <= 60)
.limit(2)
.collect(Collectors.toList());
assertArrayEquals(_students.toArray(), topTwoBetweenRange.toArray());
}
}