Using Search in Sitecore and its problems on Azure
It is a challenge working with Sitecore after a couple of years developing SharePoint project. In general, both are big “monsters”, although they have different purposes - Sitecore is a CMS and SharePoint is more like a Document Repository orientated system.
One of the components of Sharepoint that I used was the search service, which helps us to have multiple elements indexed and gives us a way to get such elements as items, pages, lists, sites, etc, using queries or sentences. A similar search service exists in Sitecore as well. There are indexes, everything is indexed and you can make queries to that service.
The Search Engine that I used for querying is Lucene. I applied the Nugget package on Visual Studio, which installed the Lucene libraries and added the following file to the “App_Config” folder on my web project: Sitecore.ContentSearch.Lucene.DefaultIndexConfiguration.config. This configuration file has some parameters, index names and it gives us the chance to add custom indexes based on our custom fields.
To generate the indexes on Sitecore we should do the following steps:
- Go to Sitecore shell menu
- Open Control Panel option under Control Panel section:
- Go to Indexing section and click on Indexing manager
- Select sitecore_master_index and sitecore_web_index under Local indexes section and click on Build or Rebuild option:
- The indexes are going to be generated/regenerated after a couple of minutes
Once we configured Sitecore, we can start working with the Search Engine. I always prefer to have a utility class, which is the responsible for getting items and making queries to the search, but everyone can use their preferred methods:
In our class, we have to add a reference to the Sitecore Content Search: using Sitecore.ContentSearch;
- We can have a root item, which is the item that begins our search (and that makes the search more bounded). For example:
var database = Sitecore.Context.Database;
var rootItem = database.GetItem(pathToRootItem);
- Open the search context
using (var searchContext = ContentSearchManager.GetIndex(new SitecoreIndexableItem(rootItem)).CreateSearchContext())
- Make the query on the Search Context using Linq language:
var resultItem = searchContext.GetQueryable<SearchResultItem>().FirstOrDefault(x => x.Paths.Contains(rootItem.ID) && x.Name.Contains(itemName));
- There are standard properties that you can use for queries (Path, Name, Created Date, etc.)
- The SearchResultItem can be converted to our model using a cast (in my case I use the GlassMapper so I convert the result item into my model item)
- You can create your own SearchResultItem custom class so you can use your own properties to query, but that is for another article!
Until now our search is working and we can get our indexed elements from Sitecore in our code, but everything is not always as we plan.
Our site needs to be hosted and one of the best places to do that is on Azure. Azure has a search engine that is used by Sitecore when we install a Sitecore on an Azure Server. When I deployed the code into the Sitecore environment on Azure, I realized that my queries were not working correctly. I was receiving different and unusual results.
After a lot of debugging and with some help of my team, we realized that the query expressions should be modified.
We noticed that queries with names or strings as parameters with or & and expressions are interpreted differently on Azure search engine. Therefore, we modified our queries to use IDs as search parameters. For example:
Old version (works on local environment but has different results on Azure):
var queryResult = searchContext.GetQueryable<SearchResultItem>().Where(x => x.Path.Contains(rootItem.Paths.ContentPath) && x.TemplateName == INews_With_ImageConstants.TemplateName);
New version (works on local environment and Azure too):
var queryResult = searchContext.GetQueryable<SearchResultItem>().Where(x => x.Paths.Contains(rootItem.ID) && (x.TemplateId == INews_With_ImageConstants.TemplateId));
You can see, it will not always be easier to change your queries or to create your queries only using ids. Although, it is the best solution we found and we expect that future Sitecore versions can handle this problems.
See you on the next post!