#8 - Some polishing of the example.
Introduced the usage of Lombok to be able to get rid off the getters and setters. Simplified the configuration to use Spring Boot's auto-configuration. The initializer is now an enum manually triggered with a MongoOperations instance. Switched from MongoTemplate to MongoOperations where possible. Polished some JavaDoc. Original pull request: #10.
This commit is contained in:
@@ -23,4 +23,4 @@
|
||||
<version>1.0.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
</project>
|
||||
|
||||
@@ -17,15 +17,21 @@ package example.springdata.mongodb.textsearch;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mongodb.core.index.TextIndexed;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
import org.springframework.data.mongodb.core.mapping.TextScore;
|
||||
|
||||
/**
|
||||
* Document representation of a {@link BlogPost} carrying annotation based information for text indexes.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Document
|
||||
@Data
|
||||
public class BlogPost {
|
||||
|
||||
private @Id String id;
|
||||
@@ -33,50 +39,4 @@ public class BlogPost {
|
||||
private @TextIndexed(weight = 2) String content;
|
||||
private @TextIndexed List<String> categories;
|
||||
private @TextScore Float score;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public List<String> getCategories() {
|
||||
return categories;
|
||||
}
|
||||
|
||||
public void setCategories(List<String> categories) {
|
||||
this.categories = categories;
|
||||
}
|
||||
|
||||
public Float getScore() {
|
||||
return score;
|
||||
}
|
||||
|
||||
public void setScore(Float score) {
|
||||
this.score = score;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BlogPost [score=" + score + ", id=" + id + ", title=" + title + ", categories=" + getCategories() + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,46 +15,35 @@
|
||||
*/
|
||||
package example.springdata.mongodb.textsearch;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
|
||||
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
|
||||
|
||||
import com.mongodb.Mongo;
|
||||
import com.mongodb.MongoClient;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
|
||||
import example.springdata.mongodb.util.BlogPostInitializer;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Configuration
|
||||
@EnableMongoRepositories
|
||||
public class MongoTestConfiguration extends AbstractMongoConfiguration {
|
||||
@EnableAutoConfiguration
|
||||
public class MongoTestConfiguration {
|
||||
|
||||
static final String DATABASE_NAME = "s2gx2014-blog";
|
||||
static final String BLOG_POST_ATOM_FEED_SOURCE = "https://spring.io/blog.atom";
|
||||
|
||||
@Override
|
||||
protected String getDatabaseName() {
|
||||
return DATABASE_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mongo mongo() throws Exception {
|
||||
return new MongoClient();
|
||||
}
|
||||
@Autowired MongoOperations operations;
|
||||
|
||||
/**
|
||||
* Initializes the repository with a predefined set of entities.
|
||||
*
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@Bean
|
||||
public BlogPostInitializer initializer() {
|
||||
return new BlogPostInitializer(BLOG_POST_ATOM_FEED_SOURCE);
|
||||
@PostConstruct
|
||||
void initialize() throws Exception {
|
||||
BlogPostInitializer.INSTANCE.initialize(operations);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,8 +52,7 @@ public class MongoTestConfiguration extends AbstractMongoConfiguration {
|
||||
* @throws Exception
|
||||
*/
|
||||
@PreDestroy
|
||||
public void dropTestDB() throws Exception {
|
||||
mongo().dropDatabase(getDatabaseName());
|
||||
void dropTestDB() throws Exception {
|
||||
operations.dropCollection(BlogPost.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,12 +22,16 @@ import java.util.List;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.mongodb.core.mapping.TextScore;
|
||||
import org.springframework.data.mongodb.core.query.TextCriteria;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* Integration tests showing the text search functionality using repositories.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(classes = { MongoTestConfiguration.class })
|
||||
@@ -44,6 +48,7 @@ public class TextSearchRepositoryTests {
|
||||
|
||||
TextCriteria criteria = TextCriteria.forDefaultLanguage().matchingAny("release");
|
||||
List<BlogPost> blogPosts = repo.findAllBy(criteria);
|
||||
|
||||
printResult(blogPosts, criteria);
|
||||
}
|
||||
|
||||
@@ -55,6 +60,7 @@ public class TextSearchRepositoryTests {
|
||||
|
||||
TextCriteria criteria = TextCriteria.forDefaultLanguage().matchingAny("release").notMatching("engineering");
|
||||
List<BlogPost> blogPosts = repo.findAllBy(criteria);
|
||||
|
||||
printResult(blogPosts, criteria);
|
||||
}
|
||||
|
||||
@@ -66,17 +72,19 @@ public class TextSearchRepositoryTests {
|
||||
|
||||
TextCriteria criteria = TextCriteria.forDefaultLanguage().matchingPhrase("release candidate");
|
||||
List<BlogPost> blogPosts = repo.findAllBy(criteria);
|
||||
|
||||
printResult(blogPosts, criteria);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort by relevance relying on the value marked with {@link org.springframework.data.mongodb.core.mapping.TextScore}.
|
||||
* Sort by relevance relying on the value marked with {@link TextScore}.
|
||||
*/
|
||||
@Test
|
||||
public void findAllBlogPostsByPhraseSortByScore() {
|
||||
|
||||
TextCriteria criteria = TextCriteria.forDefaultLanguage().matchingPhrase("release candidate");
|
||||
List<BlogPost> blogPosts = repo.findAllByOrderByScoreDesc(criteria);
|
||||
|
||||
printResult(blogPosts, criteria);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,14 +22,14 @@ import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoProperties;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.index.TextIndexDefinition;
|
||||
import org.springframework.data.mongodb.core.index.TextIndexDefinition.TextIndexDefinitionBuilder;
|
||||
import org.springframework.data.mongodb.core.query.TextCriteria;
|
||||
import org.springframework.data.mongodb.core.query.TextQuery;
|
||||
|
||||
import com.mongodb.MongoClient;
|
||||
|
||||
import example.springdata.mongodb.util.BlogPostInitializer;
|
||||
|
||||
/**
|
||||
@@ -37,16 +37,19 @@ import example.springdata.mongodb.util.BlogPostInitializer;
|
||||
*/
|
||||
public class TextSearchTemplateTests {
|
||||
|
||||
MongoTemplate template;
|
||||
MongoOperations operations;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
|
||||
template = new MongoTemplate(new MongoClient(), MongoTestConfiguration.DATABASE_NAME);
|
||||
template.dropCollection(BlogPost.class);
|
||||
MongoProperties properties = new MongoProperties();
|
||||
|
||||
operations = new MongoTemplate(properties.createMongoClient(null), properties.getMongoClientDatabase());
|
||||
operations.dropCollection(BlogPost.class);
|
||||
|
||||
createIndex();
|
||||
loadTestData();
|
||||
|
||||
BlogPostInitializer.INSTANCE.initialize(this.operations);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,7 +60,8 @@ public class TextSearchTemplateTests {
|
||||
public void findAllBlogPostsWithRelease() {
|
||||
|
||||
TextCriteria criteria = TextCriteria.forDefaultLanguage().matchingAny("release");
|
||||
List<BlogPost> blogPosts = template.find(query(criteria), BlogPost.class);
|
||||
List<BlogPost> blogPosts = operations.find(query(criteria), BlogPost.class);
|
||||
|
||||
printResult(blogPosts, criteria);
|
||||
}
|
||||
|
||||
@@ -73,7 +77,8 @@ public class TextSearchTemplateTests {
|
||||
query.setScoreFieldName("score");
|
||||
query.sortByScore();
|
||||
|
||||
List<BlogPost> blogPosts = template.find(query, BlogPost.class);
|
||||
List<BlogPost> blogPosts = operations.find(query, BlogPost.class);
|
||||
|
||||
printResult(blogPosts, criteria);
|
||||
}
|
||||
|
||||
@@ -106,13 +111,6 @@ public class TextSearchTemplateTests {
|
||||
.onField("categories") //
|
||||
.build();
|
||||
|
||||
template.indexOps(BlogPost.class).ensureIndex(textIndex);
|
||||
operations.indexOps(BlogPost.class).ensureIndex(textIndex);
|
||||
}
|
||||
|
||||
private void loadTestData() throws Exception {
|
||||
|
||||
BlogPostInitializer initializer = new BlogPostInitializer(MongoTestConfiguration.BLOG_POST_ATOM_FEED_SOURCE);
|
||||
initializer.initialize(this.template);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,11 +18,12 @@ package example.springdata.mongodb.util;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import com.sun.syndication.feed.atom.Category;
|
||||
@@ -33,47 +34,58 @@ import com.sun.syndication.feed.atom.Feed;
|
||||
import example.springdata.mongodb.textsearch.BlogPost;
|
||||
|
||||
/**
|
||||
* Component to initialize {@link BlogPost}s by accessing the latest ones from the Spring blog.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class BlogPostInitializer implements InitializingBean {
|
||||
@Slf4j
|
||||
public enum BlogPostInitializer {
|
||||
|
||||
private final String url;
|
||||
private final RestTemplate restTemplate;
|
||||
private final Converter<Entry, BlogPost> converter;
|
||||
INSTANCE;
|
||||
|
||||
@Autowired MongoTemplate mongoTemplate;
|
||||
private final RestTemplate restTemplate = new RestTemplate();
|
||||
private final Converter<Entry, BlogPost> converter = EntryConverter.INSTANCE;
|
||||
private final String url = "https://spring.io/blog.atom";
|
||||
|
||||
public BlogPostInitializer(String url) {
|
||||
/**
|
||||
* Initializes the given {@link MongoOperations} with {@link BlogPost}s from the Spring Blog.
|
||||
*
|
||||
* @param operations must not be {@literal null}.
|
||||
*/
|
||||
public void initialize(MongoOperations operations) {
|
||||
|
||||
restTemplate = new RestTemplate();
|
||||
this.converter = new EntryConverter();
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public void initialize(MongoTemplate mongoTemplate) {
|
||||
Assert.notNull(operations, "MongoOperations must not be null!");
|
||||
|
||||
ResponseEntity<Feed> feed = restTemplate.getForEntity(url, Feed.class);
|
||||
int count = 0;
|
||||
|
||||
if (feed.hasBody()) {
|
||||
for (Object entry : feed.getBody().getEntries()) {
|
||||
if (entry instanceof Entry) {
|
||||
mongoTemplate.save(converter.convert((Entry) entry));
|
||||
operations.save(converter.convert((Entry) entry));
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
initialize(this.mongoTemplate);
|
||||
log.info("Imported {} blog posts from spring.io!", count);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Converter} implementation capable of converting atom feed {@link Entry} into {@link BlogPost}.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
static class EntryConverter implements Converter<Entry, BlogPost> {
|
||||
private enum EntryConverter implements Converter<Entry, BlogPost> {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public BlogPost convert(Entry source) {
|
||||
|
||||
@@ -89,15 +101,16 @@ public class BlogPostInitializer implements InitializingBean {
|
||||
}
|
||||
|
||||
List<String> categories = new ArrayList<String>();
|
||||
|
||||
for (Object category : source.getCategories()) {
|
||||
if (category instanceof Category) {
|
||||
categories.add(((Category) category).getLabel());
|
||||
}
|
||||
}
|
||||
|
||||
post.setCategories(categories);
|
||||
|
||||
return post;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ public class ConsoleResultPrinter {
|
||||
for (BlogPost blogPost : blogPosts) {
|
||||
System.out.println(blogPost);
|
||||
}
|
||||
|
||||
System.out.println("XXXXXXXXXXXX -- XXXXXXXXXXXX -- XXXXXXXXXXXX\r\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,5 +10,7 @@
|
||||
<root level="warn">
|
||||
<appender-ref ref="console" />
|
||||
</root>
|
||||
|
||||
<logger name="example.springdata" level="info" />
|
||||
|
||||
</configuration>
|
||||
</configuration>
|
||||
|
||||
Reference in New Issue
Block a user