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…
Reference in New Issue