3. Miscellaneous Solr Operation Support

Abstract

This chapter covers additional support for Solr operations (such as faceting) that cannot be directly accessed via the repository interface. It is recommended to add those operations as custom implementation as described in Section 1.3, “Custom implementations for Spring Data repositories” .

3.1 Partial Updates

PartialUpdates can be done using PartialUpdate which implements Update .

[Note]Note
Partial updates require Solr 4.x. With Solr 4.0.0 it is not possible to update mulitvalue fields.

[Note]Note
With Solr 4.1.0 you have to take care on parameter order when setting null values. Order parameters with nulls last.

Example 3.1. 

PartialUpdate update = new PartialUpdate("id", "123");
update.add("name", "updated-name");
solrTemplate.saveBean(update);

3.2 Projection

Projections can be applied via @Query using the fields value.

Example 3.2. 

@Query(fields = { "name", "id" })
List<ProductBean> findByNameStartingWith(String name);

3.3 Faceting

Faceting cannot be directly applied using the SolrRepository but the SolrTemplate holds support for this feature.

Example 3.3. 

FacetQuery query = new SimpleFacetQuery(new Criteria(Criteria.WILDCARD).expression(Criteria.WILDCARD))
  .setFacetOptions(new FacetOptions().addFacetOnField("name").setFacetLimit(5));
FacetPage<Product> page = solrTemplate.queryForFacetPage(query, Product.class);

Facets on fields and/or queries can also be defined using @Facet . Please mind that the result will be a FacetPage .

[Note]Note
Using @Facet allows you to define place holders which will use your input parameter as value.

Example 3.4. 

@Query(value = "*:*")
@Facet(fields = { "name" }, limit = 5)
FacetPage<Product> findAllFacetOnName(Pageable page);

Example 3.5. 

@Query(value = "popularity:?0")
@Facet(fields = { "name" }, limit = 5, prefix="?1")
FacetPage<Product> findByPopularityFacetOnName(int popularity, String prefix, Pageable page);

Solr allows definition of facet parameters on a per field basis. In order to add special facet options to defined fields use FieldWithFacetParameters.

Example 3.6. 

// produces: f.name.facet.prefix=spring
FacetOptions options = new FacetOptions();
options.addFacetOnField(new FieldWithFacetParameters("name").setPrefix("spring"));
			

3.4 Terms

Terms Vector cannot directly be used within SolrRepository but can be applied via SolrTemplate. Please mind, that the result will be a TermsPage.

Example 3.7. 

TermsQuery query = SimpleTermsQuery.queryBuilder().fields("name").build();
TermsPage page = solrTemplate.queryForTermsPage(query);
			

3.5 Filter Query

Filter Queries improve query speed and do not influence document score. It is recommended to implement geospatial search as filter query.

[Note]Note
Please note that in solr, unless otherwise specified, all units of distance are kilometers and points are in degrees of latitude,longitude.

Example 3.8. 

Query query = new SimpleQuery(new Criteria("category").is("supercalifragilisticexpialidocious"));
FilterQuery fq = new SimpleFilterQuery(new Criteria("store")
  .near(new GeoLocation(48.305478, 14.286699), new Distance(5)));
query.addFilterQuery(fq);

Simple filter queries can also be defined using @Query .

[Note]Note
Using @Query allows you to define place holders which will use your input parameter as value.

@Query(value = "*:*", filters = { "inStock:true", "popularity:[* TO 3]" })
List<Product> findAllFilterAvailableTrueAndPopularityLessThanEqual3();

3.6 Time allowed for a search

It it possible to set the time allowed for a search to finish. This value only applies to the search and not to requests in general. Time is in milliseconds. Values less than or equal to zero implies no time restriction. Partial results may be returned, if there are any.

Example 3.9. 

                Query query = new SimpleQuery(new SimpleStringCriteria("field_1:value_1"));
                // Allowing maximum of 100ms for this search
                query.setTimeAllowed(100);
            

3.7 Boost document Score

Boost document score in case of matching criteria to influence result order. This can be done by either setting boost on Criteria or using @Boost for derived queries.

Example 3.10. 

Page<Product> findByNameOrDescription(@Boost(2) String name, String description);

3.7.1 Index Time Boosts

Boosting documents score can be done on index time by using @SolrDocument annotation on classes (for Solr documents) and/or @Indexed on fields (for Solr fields).

Example 3.11. 

import org.apache.solr.client.solrj.beans.Field;
import org.springframework.data.solr.repository.Boost;

@SolrDocument(boost = 0.8f)
public class MyEntity {

    @Id
    @Indexed
    private String id;
    
    @Indexed(boost = 1.0f)
    private String name;
    
    // setters and getters ...

}
	            

3.8 Select Request Handler

Select the request handler via qt Parameter directly in Query or add @Query to your method signature.

Example 3.12. 

@Query(requestHandler = "/instock")
Page<Product> findByNameOrDescription(String name, String description);

3.9 Using Join

Join attributes within one solr core by defining Join attribute of Query.

[Note]Note
Join is not available prior to solr 4.x.

Example 3.13. 

SimpleQuery query = new SimpleQuery(new SimpleStringCriteria("text:ipod"));
query.setJoin(Join.from("manu_id_s").to("id"));

3.10 Highlighting

To highlight matches in search result add HighlightOptions to the SimpleHighlightQuery. Providing HighlightOptions without any further attributes will highlight apply highlighting on all fields within a SolrDocument.

[Note]Note
Field specific highlight parameters can be set by adding FieldWithHighlightParameters to HighlightOptions.

Example 3.14. 

SimpleHighlightQuery query = new SimpleHighlightQuery(new SimpleStringCriteria("name:with"));
query.setHighlightOptions(new HighlightOptions());
HighlightPage<Product> page = solrTemplate.queryForHighlightPage(query, Product.class);

Not all parameters are available via setters/getters but can be added directly.

Example 3.15. 

SimpleHighlightQuery query = new SimpleHighlightQuery(new SimpleStringCriteria("name:with"));
query.setHighlightOptions(new HighlightOptions().addHighlightParameter("hl.bs.country", "at"));

In order to apply Highlighting to derived queries use @Highlight. If no fields are defined highlighting will be aplied on all fields.

Example 3.16. 

@Highlight(prefix = "<b>", postfix = "</b>")
HighlightPage<Product> findByName(String name, Pageable page);

3.11 Using Functions

Solr supports several functional expressions within queries. Followig functions are supported out of the box. Custom functions can be added by implementing Function

Table 3.1. Functions

ClassSolr Function
CurrencyFunction currency(field_name,[CODE])
DefaultValueFunction def(field|function,defaultValue)
DistanceFunction dist(power, pointA, pointB)
DivideFunction div(x,y)
ExistsFunction exists(field|function)
GeoDistanceFunction geodist(sfield, latitude, longitude)
GeoHashFunction geohash(latitude, longitude)
IfFunction if(value|field|function,trueValue,falseValue)
MaxFunction max(field|function,value)
NotFunction not(field|function)
ProductFunction product(x,y,...)
QueryFunction query(x)
TermFrequencyFunction termfreq(field,term)


Example 3.17. 

SimpleQuery query = new SimpleQuery(new SimpleStringCriteria("text:ipod"));
query.addFilterQuery(new FilterQuery(Criteria.where(QueryFunction.query("name:sol*"))));