Big Data/Analytics Zone is brought to you in partnership with:

I am a Java Web Developer, Blogger, technology enthusiast and 3D graphic hobbyist. Mostly I am writing about Java related technologies including Java EE, Spring and Grails. Michael is a DZone MVB and is not an employee of DZone and has posted 18 posts at DZone. You can read more from them at their website. View Full User Profile

Getting started with Spring Data Solr

12.12.2013
| 12989 views |
  • submit to reddit

Creating a Repository

Spring Data uses repositories to simplify the usage of various data access technologies. A repository is basically an interface whose implementation is dynamically generated by Spring Data on application start. The generated implementation is based on naming conventions used in the repository interface. If this is new to you I recommend reading Working with Spring Data Repositories.

Spring Data Solr uses the same approach. We use naming conventions and annotations inside interfaces to define the methods we need to access Solr features. We start with a simple repository that contains only one method (we will add more later):

public interface BookRepository extends SolrCrudRepository<Book, String> {
 
  List<Book> findByName(String name);
 
}

We get some common methods like save(), findAll(), delete() or count() in the repository by extending SolrCrudRepository. With the definition of the interface method findByName(String name) we tell Spring Data Solr to create a method implementation that queries Solr for a list of books. The book names in this list should match the passed parameter.

The repository implementation can be injected into other classes using Spring's DI functionality. In this example we inject the repository into a simple JUnit test:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Application.class, loader=SpringApplicationContextLoader.class)
public class BookRepositoryTests {
   
  @Autowired
  private BookRepository bookRepository;
   
  ...
}

Adding a Document to Solr

Now it is time to add some books to Solr. Using our repository this is a very easy job:

private void addBookToIndex(String name, String description, Category... categories) {
  Book book = new Book();
  book.setName(name);
  book.setDescription(description);
  book.setCategories(Arrays.asList(categories));
  book.setId(UUID.randomUUID().toString());
  bookRepository.save(book);
}
 
private void createSampleData() {
  addBookToIndex("Treasure Island", "Best seller by R.L.S.", Category.ADVENTURE);
  addBookToIndex("The Pirate Island", "Oh noes, the pirates are coming!", Category.ADVENTURE, Category.HUMOR);
  ...
}

Adding Pagination and Boosting

Assume we have an application where users are able to search for books. We need to find books whose name or description match the search query given by the user. For performance reasons we want to add some kind of pagination which shows only 10 search results at once to the user.

Let's create a new method in our repository interface for this:

Page<Book> findByNameOrDescription(@Boost(2) String name, String description, Pageable pageable);

The method name findByNameOrDescription tells Spring Data Solr to query for book objects whose name or description match the passed parameters. To support pagination we added the Pageable parameter and changed the return type from List<Book> to Page<Book>. By adding the @Boost annotation to the name parameter we are boosting books whose name matches the search parameter. This makes sense because those books are typically at higher Interest for the user.

If we now want to query for the first page containing 10 elements we just have to do:

Page<Book> booksPage = bookRepository.findByNameOrDescription(searchString, searchString, new PageRequest(0, 10));

Besides the first 10 search results Page<Book> provides some useful methods for building pagination functionality:

booksPage.getContent()       // get a list of (max) 10 books
booksPage.getTotalElements() // total number of elements (can be >10)
booksPage.getTotalPages()    // total number of pages
booksPage.getNumber()        // current page number
booksPage.isFirstPage()      // true if this is the first page
booksPage.hasNextPage()      // true if another page is available
booksPage.nextPageable()     // the pageable for requesting the next page
...
Published at DZone with permission of Michael Scharhag, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)