At the end of October, I attended a 3-days Solr training. It was very interesting, in light of the former Elastic Search talk I attended mid-year. As an old Spring Data fan, when I found out Spring Data offered a Solr module, I jumped at the chance to try it.

In this case, I’m well aware that an abstraction layer over Solr doesn’t mean we can easily change the underlying datastore: Solr is designed as an inverted index, while other Spring Data modules are much more specialized (JPA, MongoDB, etc.). However, there are still some advantages of using Spring Data over Solr:

Quick prototyping, when you don’t need the whole nine yards

Use Solr when most of the team already knows about Spring Data and not Solr

Spring integration from the bottom

Last but not least important of all, you can easily switch between the embedded Solr and the standalone one. Spring Data nicely wraps both the Solrj API and HTTP behind its own API. If you think this is not a relevant use-case as it never will happen, think about integration testing

After having initialized Solr with relevant data, here are steps you have to go through to start developing:

The initial step is to configure the Spring context with the underlying Solr. Spring Data Solr requires a bean named solrTemplate of type SolrOperations . Let use the JavaConfig for this: @Configuration @EnableSolrRepositories ( "ch.frankel.blog.springdata.solr.repository" ) public class JavaConfig { @Bean protected HttpSolrServerFactoryBean solrServerFactory () { HttpSolrServerFactoryBean factory = new HttpSolrServerFactoryBean (); factory . setUrl ( "http://localhost:8983/solr" ); return factory ; } @Bean public SolrOperations solrTemplate () throws Exception { return new SolrTemplate ( solrServerFactory (). getObject ()); } } Create the managed entity. All fields stored in Solr have to be annotated with @Field . If the entity attribute name is different from Solr field name, @Field accepts a value to override the name: public class Loan { @Field private String id ; @Field ( "gov_type" ) private String governmentType ; // Getters and setters } Create the repository interface: either inherit from SolrRepository<Bean,ID> or SolrCrudRepository<Bean,ID> . Note the former only provides the count() method. public interface LoanRepository extends SolrRepository < Loan , String > {} Add query methods to the former interface: Simple query methods benefit from Spring Data parsing: List<Loan> findByLoanType(String) will translate into ?q=loan_type:…​

More advanced queries (or method whose name do not follow the pattern) should be annotated with @Query : @Query("state_name:[* TO *]") will find all loans which have a value for state_name . The annotation can bind as many parameters as necessary, through the use of ?x where x is the parameter index in the method parameters list.

Facets are also handled through the @Facet annotation, which takes the field names the facet should use. This changes the method signature, though, to a FacetPage and it is up to the calling method (probably located the service layer) to handle that.

The final class should look something like that, which is awesome considering all capabilities it provides:

public interface LoanRepository extends SolrRepository < Loan , String > { List < Loan > findByLoanType ( String loan ); List < Loan > findByTitleContaining ( String title ); @Query ( "state_name:[* TO *]" ) List < Loan > findLocalized (); @Query ( "*:*" ) @Facet ( fields = "loan_type" ) FacetPage < Loan > findAllLoanTypes ( Pageable page ); }