Solr Facet add link



This is about how to link the resulting facet data from Solr on your web application.
I am using Django as the front-end framework. But this solution applies to any language.

The problem

You have modeled your data and indexed to Solr. You will show facets on your web application to facilitate the navigation on your site to the users. You get faceted data from Solr; so far so good.

The problem arises when you need to link your facet item to any destination other than the value of the facet itself, because Solr faceted data returns only the field value and count of occurences.

The example below is a simplification of the Solr facet web page 1, and show you how the json facet returns:

{  "facet_counts":{
   "facet_queries":{},
   "facet_fields":{
     "categories":[
       "electronics",14,
       "currency",4,
       "memory",3,
       "connector",2,
       "graphics card",2]},
}}}

As you can see, you have only the string and the total count of all match results of the strings for the referred field.

As per Solr docs:
“Faceting is the arrangement of search results into categories based on indexed terms. Searchers are presented with the indexed terms, along with numerical counts of how many matching documents were found were each term. Faceting makes it easy for users to explore search results, narrowing in on exactly the results they are looking for.”

Build link

With that information returned from Solr, you can draw your facet at the presentation layer and build links to your server. If you build a standard get URL or a smart url parameter, it shows like this:

What if you want to link to a page, e.g for a detail page of the object? There is not much that can be made, since we have only the string and count returned from Solr facet.
There are some options in order to accomplish that and I will show you three of them. One at the Solr level and two at the Django level.

Push link information to Solr

At the Solr level you can stick the information you want along with the indexed data. You can see here 2 this simple approach that requires you to join two different data on the same field.
There are two points that I don’t like much. 
  1. You have to mix different data on the same string field of the facet, and split at the server level.
  2. If you are point to a specific page, you don’t have the full URL with slug.

Build link at Django layer

You can manage to build links at the Django layer. I will show you two distinct solutions that relies on the same data source at server level. This looks more syntactic to me.

The second example that I will describe is more extensible and I recomend.

Remember that you will build links based on the information you have recovered from Solr, and you are not indexing extra contents as the former solution.
On the given Solr JSON facet example, if you want to ask for all documents that are of the category electronics, you can ask then like this e.g:





If we need to get a detail page of electronics, you have any information but the string “electronics”.

Due to Solr´s nature of document indexing and inverted index, the format of the data stored and returned of documents is the actual index. Which means that the value of the facets are the text stored, and if you want to recover documents based on that index you have to ask for that index.

If you have analyzed your data and indexed right, you have uniques keywords for each category. That is very important, because you can go to your Django ORM and get from model your object “electronic” of the model “category”.



my_category = Category.objects.get(category=”electronics)
my_category_url = my_category.get_absolute_url()


The URL is returned:





With this method, you have the complete URL, with id of the object and slug.

There are two layers where you can build the urls. On template tags, and on a RedirectView.

Template tag
This is not the best place to build your urls, because you may have lots of facet elements, which can overload and slow your system response. But for the records, you can write your template tag like this:


@register.simple_tag(name=’get_category’)
def get_category(category):
category = Category.objects.get(category=category)
return category.get_absolute_url()

Then on templates:

RedirectView
This is more efficient way to build your URLs, because you build them on demand.

Write a RedirectView like this:

class redirectResolverView(View):
   def get(self, category):
   category = Category.objects.get(category=category)
   return category.get_absolute_url()


Then on templates:



Add that class to your urls.py and that is it.

You can make this redirectResolverView more generic, to respond to different models.
And make sure to make a filter to change the forward slash character to avoid problems on your smart urls on Django.


References:

1. https://lucene.apache.org/solr/guide/6_6/faceting.html
2. https://stackoverflow.com/a/18284430




Popular posts from this blog

Atom - Jupyter / Hydrogen

Design Patterns

Robson Koji Moriya disambiguation name