Faceted Search with Sitecore

Facets are used to group and classify content items, it’s used to aggregate the count of terms in a field to help a user filter their search more and more to get to the specific results they are after.

Search-Facets

As per the documentation of SOLR, facets are described as “… the arrangement of search results into categories based on indexed terms…”. faceting makes it really easy for the end users to look and explore for something which they are looking for. An example can be amazon.com which provides faceted navigation based on the selected keyword, which facilitates users to do look into specific category and narrowing down their results.

Sitecore+Search

Lucene and SOLR both provides support for Facets using ContentSearch API,which means you write facets one and that can be re-used for other search engines as well.
Using ContentSearch API we can use FacetOn() method on the IQueryable<T> instance to set what to facet on, and then call GetFactes() method to get the list of results.

context.GetQueryable<SearchResultModel>().Where(predicate).FacetOn(x => x[“ProperyName”], 1).GetFacets();

The second parameter to FacetOn() method is optional, it’s a min count and if we provide the min count, it means it’s going to return facets that is greater then equal >= to the value which has been set there.

Complete example:

using (IProviderSearchContext context = selectedIndex.CreateSearchContext())
{

var searchResults = context.GetQueryable<SearchResultItem>().Where(predicate).FacetOn(x => x[“ProperyName”], 1).GetResults();

// To check if we have any facet categories exists or not…
if (searchResults.Facets != null && searchResults.Facets.Categories.Any())

{

// Get all the facet categories…

// get facet category values and fetch facet name and aggregate count for each

// var facetName=facet.Name;

//  var facetCount= facet.AggregateCount;

}

}

If we want to facet based on multiple fields, we can just do it with adding chain of method calls and we should be all set to go.

context.GetQueryable<SearchResultItem>().Where(predicate).FacetOn(x => x[“Propery1Name”], 1).FacetOn(x => x[“Propery2Name”], 1).GetFacets();

Facets with tokenized fields:

Default field type in SOLR is tokenized which means it will split the string value in your index, and if the facet field value has space on it, it will be considered as two facets, as a workaround we should create a new computed untokenized index field and use that field instead.

Please see the below page for more details:

Sitecore Drop List Faceting Phrase Space Issue with Solr Search

Hope this helps.

Happy learning  and wish you all a very happy New Year 2018 🙂

Perform basic search with Sitecore

In this blog post I’ll be doing a introduction of the ContentSearch API found in Sitecore followed with a basic search example.
There are several articles which are available, but i will show a very simple working example of it.

Sitecore+Search

ContentSearch API:

ContentSearch API acts like an abstraction over the low level details of search technologies like Lucene or Solr. Sitecore provides an API that can be used to work with Lucene or SOLR, there might be some changes between the two, but those will be just configuration changes.

Same code can be leveraged for Lucene or SOLR, this also helps and provides flexibility during Sitecore upgrade or switching the search providers, you will end up making configuration changes to match the version and you will be all set.

It depends on the business requirements what search provider best fits your needs, there is official documentation provided by Sitecore on Lucene Or SOLR- https://doc.sitecore.net/sitecore_experience_platform/setting_up_and_maintaining/search_and_indexing/indexing/using_solr_or_lucene

Sample Search:

Here are the steps that are required to perform a simple search.

  1. Get the search index you want to use.
  2. Get the search context (which is also known as opening the connection) and
  3. Use the search context and perform queries.

Get the search index you want to use:

We need to get the index that we are going to use in the application, it can be out of the box indexes or custom indexes that we created, some of the indexes that can be referred are as follows:

  • sitecore_master_index
  • sitecore_web_index
  • sitecore_product_index (custom index)

We need to call GetIndex() method of ContentSearchManager class, which returns ISearchIndex instance.

ISearchIndex selectedIndex = ContentSearchManager.GetIndex(“sitecore_master_index”);

Once we have the index we can get other index details out of it, and can also perform operations like rebuilding of the index if required.

Get the search context:

This is more of opening a connection to search index, once we have the index available, next step is to create search context which allows us to perform search queries and operations against the selected index.
We create the search context using CreateSearchContext() method.

using (IProviderSearchContext context = selectedIndex.CreateSearchContext())
{

}

The search context is wrapped in using statement, so that it can be disposed when we are done performing the queries.

Perform queries:

Once we have the search context, it can be used to perform queries,
By using GetQueryable<T>() we can define our LINQ statements for filtering and getting the results.

using (IProviderSearchContext context = selectedIndex.CreateSearchContext())
{
var searchResults = context.GetQueryable<SearchResultItem>().Where(x => x.Content.Contains(“hello”));
}

By default the API will map to the SearchResultItem class for the result

This is a very basic example where we covered how get the index for search, create the context so that queries can be performed and finally using the context to perform the queries.

I hope this helps someone who is writing it’s first search code in Sitecore.

Happy learning 🙂

Please let me know your thoughts and feedback.

Return null or String.Empty for Computed fields in Sitecore

It is quite obvious that we have to create computed fields in Sitecore, to process some of the information well before it get indexed, and not processing it while requesting for the data.

ankit-sitecore-download

There are chances when you don’t find any value to be added to you computed field, in those cases we can return either null or String.Empty().

Returning null basically tells that there is nothing to be indexed, and it won’t take any space in your index, but when we return string.Empty() , it actually creates an entry in index with no value.

Returning String.Empty() is helpful when you want to validate something based on empty string, but most of the case it is not worth.

Also, consider a case when you are dealing with several thousands Sitecore items, and if you are going to return String.Empty() for few thousands also, it will just get indexed that takes up space in you index.

We should carefully think about this, if there is a need to return String.Empty() we should do the same, but if not we should always try to return null.

Hope this helps someone.

Happy learning 🙂