BAEL-1324 A Simple Tagging Implementation with Elasticsearch (#3464)
* Christopher Franklin A Simple Tagging Implementation with Elasticsearch Modifying the existing Spring Data Elasticsearch example to use the tags already on the model. Also added a number of tests as examples of how to use the tags.
This commit is contained in:
		
							parent
							
								
									af3edc477d
								
							
						
					
					
						commit
						9f1429b067
					
				| @ -1,12 +1,13 @@ | |||||||
| package com.baeldung.spring.data.es.repository; | package com.baeldung.spring.data.es.repository; | ||||||
| 
 | 
 | ||||||
| import com.baeldung.spring.data.es.model.Article; |  | ||||||
| import org.springframework.data.domain.Page; | import org.springframework.data.domain.Page; | ||||||
| import org.springframework.data.domain.Pageable; | import org.springframework.data.domain.Pageable; | ||||||
| import org.springframework.data.elasticsearch.annotations.Query; | import org.springframework.data.elasticsearch.annotations.Query; | ||||||
| import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; | import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; | ||||||
| import org.springframework.stereotype.Repository; | import org.springframework.stereotype.Repository; | ||||||
| 
 | 
 | ||||||
|  | import com.baeldung.spring.data.es.model.Article; | ||||||
|  | 
 | ||||||
| @Repository | @Repository | ||||||
| public interface ArticleRepository extends ElasticsearchRepository<Article, String> { | public interface ArticleRepository extends ElasticsearchRepository<Article, String> { | ||||||
| 
 | 
 | ||||||
| @ -14,4 +15,10 @@ public interface ArticleRepository extends ElasticsearchRepository<Article, Stri | |||||||
| 
 | 
 | ||||||
|     @Query("{\"bool\": {\"must\": [{\"match\": {\"authors.name\": \"?0\"}}]}}") |     @Query("{\"bool\": {\"must\": [{\"match\": {\"authors.name\": \"?0\"}}]}}") | ||||||
|     Page<Article> findByAuthorsNameUsingCustomQuery(String name, Pageable pageable); |     Page<Article> findByAuthorsNameUsingCustomQuery(String name, Pageable pageable); | ||||||
|  | 
 | ||||||
|  |     @Query("{\"bool\": {\"must\": {\"match_all\": {}}, \"filter\": {\"term\": {\"tags\": \"?0\" }}}}") | ||||||
|  |     Page<Article> findByFilteredTagQuery(String tag, Pageable pageable); | ||||||
|  | 
 | ||||||
|  |     @Query("{\"bool\": {\"must\": {\"match\": {\"authors.name\": \"?0\"}}, \"filter\": {\"term\": {\"tags\": \"?1\" }}}}") | ||||||
|  |     Page<Article> findByAuthorsNameAndFilteredTagQuery(String name, String tag, Pageable pageable); | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,9 +1,10 @@ | |||||||
| package com.baeldung.spring.data.es.service; | package com.baeldung.spring.data.es.service; | ||||||
| 
 | 
 | ||||||
| import com.baeldung.spring.data.es.model.Article; |  | ||||||
| import org.springframework.data.domain.Page; | import org.springframework.data.domain.Page; | ||||||
| import org.springframework.data.domain.Pageable; | import org.springframework.data.domain.Pageable; | ||||||
| 
 | 
 | ||||||
|  | import com.baeldung.spring.data.es.model.Article; | ||||||
|  | 
 | ||||||
| public interface ArticleService { | public interface ArticleService { | ||||||
|     Article save(Article article); |     Article save(Article article); | ||||||
| 
 | 
 | ||||||
| @ -15,6 +16,10 @@ public interface ArticleService { | |||||||
| 
 | 
 | ||||||
|     Page<Article> findByAuthorNameUsingCustomQuery(String name, Pageable pageable); |     Page<Article> findByAuthorNameUsingCustomQuery(String name, Pageable pageable); | ||||||
| 
 | 
 | ||||||
|  |     Page<Article> findByFilteredTagQuery(String tag, Pageable pageable); | ||||||
|  | 
 | ||||||
|  |     Page<Article> findByAuthorsNameAndFilteredTagQuery(String name, String tag, Pageable pageable); | ||||||
|  | 
 | ||||||
|     long count(); |     long count(); | ||||||
| 
 | 
 | ||||||
|     void delete(Article article); |     void delete(Article article); | ||||||
|  | |||||||
| @ -1,12 +1,13 @@ | |||||||
| package com.baeldung.spring.data.es.service; | package com.baeldung.spring.data.es.service; | ||||||
| 
 | 
 | ||||||
| import com.baeldung.spring.data.es.repository.ArticleRepository; |  | ||||||
| import com.baeldung.spring.data.es.model.Article; |  | ||||||
| import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||||
| import org.springframework.data.domain.Page; | import org.springframework.data.domain.Page; | ||||||
| import org.springframework.data.domain.Pageable; | import org.springframework.data.domain.Pageable; | ||||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||||
| 
 | 
 | ||||||
|  | import com.baeldung.spring.data.es.model.Article; | ||||||
|  | import com.baeldung.spring.data.es.repository.ArticleRepository; | ||||||
|  | 
 | ||||||
| @Service | @Service | ||||||
| public class ArticleServiceImpl implements ArticleService { | public class ArticleServiceImpl implements ArticleService { | ||||||
| 
 | 
 | ||||||
| @ -42,6 +43,16 @@ public class ArticleServiceImpl implements ArticleService { | |||||||
|         return articleRepository.findByAuthorsNameUsingCustomQuery(name, pageable); |         return articleRepository.findByAuthorsNameUsingCustomQuery(name, pageable); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     @Override | ||||||
|  |     public Page<Article> findByFilteredTagQuery(String tag, Pageable pageable) { | ||||||
|  |         return articleRepository.findByFilteredTagQuery(tag, pageable); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public Page<Article> findByAuthorsNameAndFilteredTagQuery(String name, String tag, Pageable pageable) { | ||||||
|  |         return articleRepository.findByAuthorsNameAndFilteredTagQuery(name, tag, pageable); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     @Override |     @Override | ||||||
|     public long count() { |     public long count() { | ||||||
|         return articleRepository.count(); |         return articleRepository.count(); | ||||||
|  | |||||||
| @ -46,14 +46,22 @@ public class ElasticSearchIntegrationTest { | |||||||
| 
 | 
 | ||||||
|         Article article = new Article("Spring Data Elasticsearch"); |         Article article = new Article("Spring Data Elasticsearch"); | ||||||
|         article.setAuthors(asList(johnSmith, johnDoe)); |         article.setAuthors(asList(johnSmith, johnDoe)); | ||||||
|  |         article.setTags("elasticsearch", "spring data"); | ||||||
|         articleService.save(article); |         articleService.save(article); | ||||||
| 
 | 
 | ||||||
|         article = new Article("Search engines"); |         article = new Article("Search engines"); | ||||||
|         article.setAuthors(asList(johnDoe)); |         article.setAuthors(asList(johnDoe)); | ||||||
|  |         article.setTags("search engines", "tutorial"); | ||||||
|         articleService.save(article); |         articleService.save(article); | ||||||
| 
 | 
 | ||||||
|         article = new Article("Second Article About Elasticsearch"); |         article = new Article("Second Article About Elasticsearch"); | ||||||
|         article.setAuthors(asList(johnSmith)); |         article.setAuthors(asList(johnSmith)); | ||||||
|  |         article.setTags("elasticsearch", "spring data"); | ||||||
|  |         articleService.save(article); | ||||||
|  | 
 | ||||||
|  |         article = new Article("Elasticsearch Tutorial"); | ||||||
|  |         article.setAuthors(asList(johnDoe)); | ||||||
|  |         article.setTags("elasticsearch"); | ||||||
|         articleService.save(article); |         articleService.save(article); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -78,12 +86,22 @@ public class ElasticSearchIntegrationTest { | |||||||
| 
 | 
 | ||||||
|     @Test |     @Test | ||||||
|     public void givenCustomQuery_whenSearchByAuthorsName_thenArticleIsFound() { |     public void givenCustomQuery_whenSearchByAuthorsName_thenArticleIsFound() { | ||||||
|  |         final Page<Article> articleByAuthorName = articleService.findByAuthorNameUsingCustomQuery("Smith", new PageRequest(0, 10)); | ||||||
|  |         assertEquals(2L, articleByAuthorName.getTotalElements()); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|         final Page<Article> articleByAuthorName = articleService |     @Test | ||||||
|           .findByAuthorNameUsingCustomQuery("John Smith", new PageRequest(0, 10)); |     public void givenTagFilterQuery_whenSearchByTag_thenArticleIsFound() { | ||||||
|  |         final Page<Article> articleByAuthorName = articleService.findByFilteredTagQuery("elasticsearch", new PageRequest(0, 10)); | ||||||
|         assertEquals(3L, articleByAuthorName.getTotalElements()); |         assertEquals(3L, articleByAuthorName.getTotalElements()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenTagFilterQuery_whenSearchByAuthorsName_thenArticleIsFound() { | ||||||
|  |         final Page<Article> articleByAuthorName = articleService.findByAuthorsNameAndFilteredTagQuery("Doe", "elasticsearch", new PageRequest(0, 10)); | ||||||
|  |         assertEquals(2L, articleByAuthorName.getTotalElements()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     @Test |     @Test | ||||||
|     public void givenPersistedArticles_whenUseRegexQuery_thenRightArticlesFound() { |     public void givenPersistedArticles_whenUseRegexQuery_thenRightArticlesFound() { | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -191,4 +191,16 @@ public class ElasticSearchQueryIntegrationTest { | |||||||
|         final List<Article> articles = elasticsearchTemplate.queryForList(searchQuery, Article.class); |         final List<Article> articles = elasticsearchTemplate.queryForList(searchQuery, Article.class); | ||||||
|         assertEquals(2, articles.size()); |         assertEquals(2, articles.size()); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenBoolQuery_whenQueryByAuthorsName_thenFoundArticlesByThatAuthorAndFilteredTag() { | ||||||
|  |         final QueryBuilder builder = boolQuery().must(nestedQuery("authors", boolQuery().must(termQuery("authors.name", "doe")))) | ||||||
|  |             .filter(termQuery("tags", "elasticsearch")); | ||||||
|  | 
 | ||||||
|  |         final SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(builder) | ||||||
|  |             .build(); | ||||||
|  |         final List<Article> articles = elasticsearchTemplate.queryForList(searchQuery, Article.class); | ||||||
|  | 
 | ||||||
|  |         assertEquals(2, articles.size()); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user