Spring Data Solr Dynamic Queries

In this article of Spring Data Solr Dynamic Queries, we will learn how to write dynamic queries using Spring Data Solr repositories. We will see several cases of dynamic queries for the Solr Core.

We will now implement a dynamic search function with Spring Data Solr. Although our search function is rather simple, we should now be able to implement more complex queries as well.
Spring Data Solr Dynamic Queries
In the article, I will create some dynamic queries that are mostly required at time of development for your real projects such as filter queries, faceting, pivoting, and grouping etc. Let’s see the following sections about Spring Data Solr Dynamic Queries:

Spring Data Solr Dynamic Queries

There are the following queries related to the Solr in the Spring Data Solr Queries:

Projection Solr Query

Projections can be applied via @Query using the value of the field.

@Query(fields = { "oname", "oid" })
List<Order> findByOrderNameStartingWith(String name);

Faceting Solr Query

Let’s see faceting query using the SolrTemplate, it holds support for this feature.

FacetQuery query = new SimpleFacetQuery(new Criteria(Criteria.WILDCARD).expression(Criteria.WILDCARD))
.setFacetOptions(new FacetOptions().addFacetOnField("oname").setFacetLimit(5));

FacetPage<Order> page = solrTemplate.queryForFacetPage("Order", query, Order.class);

In the above code snippet, you have seen how to write facet query using SolrTemplate and FacetQuery. The FacetOptions class provides a way to set facet fields and you can also set facet limit using setFacetLimit() method. The FacetQuery returns result in a FacetPage.

You can also define the Facets on fields and/or queries using @Facet annotation. As similar to above that the result will be a FacetPage. You can define placeholders which will use your input parameter as the value using @Facet annotation, let’s see as the following code snippet:

@Query(value = "*:*")
@Facet(fields = { "oname" }, limit = 5)
FacetPage<Order> findAllFacetOnOName(Pageable page);

@Query(value = "odesc:?0")
@Facet(fields = { "oname" }, limit = 5, prefix="?1")
FacetPage<Order> findByOrderDescFacetOnName(Sttring orderDesc, String prefix, Pageable page);

As you have seen in the above faceting Solr queries, you can use either SolrTemplate or @Facet annotation in the Spring Data Solr repository to make a facet query. In the next section, we will discuss how to fire a Pivot faceting query.

Pivot Faceting Solr Query

Spring Data Solr also supports the Pivot faceting Solr queries using @Facet annotation as follows:

public interface SolrOrderRepository{

@Facet(pivots = @Pivot({ "category", "product" }, pivotMinCount = 0))
FacetPage<Order> findByOrderTitle(String title, Pageable page);

@Facet(pivots = @Pivot({ "category", "product" }))
FacetPage<Order> findByOrderDesc(String orderDesc, Pageable page);

}

As you have seen in the above code snippet how to write the Pivot Faceting Solr Query. Let’s move to the next section and learn how to fire Solr queries by the grouping of results and field collapsing.

Result Grouping / Field Collapsing

Result grouping cannot directly be used within SolrRepository but can be applied via SolrTemplate. Please mind, that the result will be a GroupPage.

Field field = new SimpleField("popularity");
Function func = ExistsFunction.exists("description");
Query query = new SimpleQuery("inStock:true");

SimpleQuery groupQuery = new SimpleQuery(new SimpleStringCriteria("*:*"));
GroupOptions groupOptions = new GroupOptions()
.addGroupByField(field)
.addGroupByFunction(func)
.addGroupByQuery(query);
groupQuery.setGroupOptions(groupOptions);

GroupPage<Order> page = solrTemplate.queryForGroupPage("Order", query, Order.class);

GroupResult<Order> fieldGroup = page.getGroupResult(field);
GroupResult<Order> funcGroup = page.getGroupResult(func);
GroupResult<Order> queryGroup = page.getGroupResult(query);

Let’s see how to write filter Solr queries in the next section.

Filter Solr Query

In this section, we will see how to write filter Solr query. The Filter Queries improve query speed without impacting document score. It is recommended to implement geospatial search as filter query.

NOTE: In this distance based filter Solr query, all units of distance are kilometres and points are in degrees of latitude, longitude.

Let’s see the following filter Solr query:

Query query = new SimpleQuery(new Criteria("category").is("java-book"));

FilterQuery fq = new SimpleFilterQuery(new Criteria("shops")
  .near(new Point(43.2012413, 13.534223), new Distance(3)));

query.addFilterQuery(fq);

The above filer Solr query we can use with the SolrTemplate. You can also create simple filter queries by using @Query annotation. The @Query annotation allows you to define placeholders which use to take your input parameter as value. Let’s see the following query:

@Query(value = "*:*", filters = { "category:java-book", "rank:[* TO 5]" })
List<Book> findAllJavaBookAndRankLessThanEqual5();

In the above code snippet, we have written a Solr query to find all Java books whose rank less than or equal to 5. In the next section, we will learn to apply Highlighting to matches in the search result.

Highlighting Solr Query Results

Spring Data Solr provides the SimpleHighlightQuery class to highlight matches in the search result by adding HighlightOptions with it. So, you have to provide HighlightOptions with attributes by adding FieldWithHighlightParameters to HighlightOptions otherwise it will apply to highlight on all fields within a SolrDocument. Let’s see the following code snippet:

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

Using with attributes:

SimpleHighlightQuery query = new SimpleHighlightQuery(new SimpleStringCriteria("oname:with"));
query.setHighlightOptions(new HighlightOptions());
HighlightPage<Order> page = solrTemplate.queryForHighlightPage("Order", query, Order.class);
query.setHighlightOptions(new HighlightOptions().addHighlightParameter("hl.bs.country", "at"));

Same things you can also do by using @Highlight annotation. If no fields are defined highlighting will be applied in all fields.

@Highlight(prefix = "<b>", postfix = "</b>")
HighlightPage<Order> findByOrderName(String orderName, Pageable page);

As you can see in the above code snippet, the return result of a Solr query will be highlighted using given prefix and postfix attribute. Let’s see how to implement spellchecking functionality using the Spring Data Solr in the following section:

Spellchecking

This feature of the Solr offers search term suggestions based on the actual query. Let’s see the following code snippet:

The following code snippet has used the Spellcheck Options. Spellcheck query parameters are added to request when SpellcheckOptions are set.

SimpleQuery q = new SimpleQuery("oname:andr");

q.setSpellcheckOptions(SpellcheckOptions.spellcheck()
.dictionaries("dict1", "dict2")
.count(5)
.extendedResults());

q.setRequestHandler("/spell");

SpellcheckedPage<Order> orders = solrTemplate.query(q, Order.class);

Enable spell check by setting SpellcheckOptions. Sets spellcheck=on request parameter.

In the above code snippet, there are the following to be noticed:

  • Set up the dictionaries to use for lookup.
  • Set the max number of suggestions to return.
  • Enable extended results including term frequency etc.
  • Set the request handler capable of processing suggestions.
  • Execute the query.

We have seen how to write a query for spellcheck. Let’s see how to write this query using annotation in the following section:

Using @Spellcheck annotation

Let’s see in the following code snippet and how to use @Spellcheck annotation to allow usage of the spellcheck feature on Repository level.

public interface SolrOrderRepository extends Repository<Order, Long> {

@Query(requestHandler = “/spell”)
@Spellcheck(dictionaries = { “dict1”, “dic2” }, count=5, extendedResults = true)
SpellcheckedPage findByOrderName(String orderName, Pageable page);

}

We have seen in this article, how to write dynamic Solr queries either using annotations or SolrTemplate.

Thanks for learning with the Dineshonjava!!!

Previous
Next