- In Part 1, we talked about interacting and consuming the search service
- In Part 2, we discussed a Tagging strategy to allow for a Filtered Search to be possible
- In Part 3, we looked at our service layer which worked with our Ajax calls
Today, we are going to dive into our search service and talk about some of the customizations we did to make Lucene and Sitecore do what we wanted from an Indexing and Search standpoint. If you recall from Part 3 (or by looking at the above screenshot), we had a piece of code that would create a new Searcher and call the GetItem
s method passing in the SearchParam
s we created based on the Ajax call that was being executed. Now we are going to dive into what the Searcher
class is.
Our Searcher
class is just a modified version of the code that you can get from Sitecore's Shared Source library and you can watch a webinar to get more details about it here so I won't go into a lot of detail. Instead, I will just go over some of the modifications I have made. Above, you can see that we have an additional call to an ApplyTagFilter
method that will help us filter by the Tag
s that were checked by the user in our UI.
The ApplyTagFilter
method will iterate through the GUIDs in our Tag
collection and add them as an OR criteria to our query. Seeing how our Tag
s are GUIDs and therefore unique, you will notice we are just querying against the BuiltIn.Content
field.
Indexing
So the AdvancedDatabaseCrawler
is inheriting from the standard Sitecore DatabaseCrawler
. One requirement our client had is that they want the ability to hide an item from search fairly easily even if the actual content is available on the site. The way I accomplished this is to simply have a Field
on the Base Page Template called "Hide From Search". Keying off of this field, we can then tell Sitecore to not index the item if this field is checked.
When setting up the configuration for each index, you can specify the boost, but I have taken it a step further here allowing the Content Managers to overwrite the Boost associated with the Template or Page.
So above, we are taking the default Boost associated with the document based on the configuration and adjusting it with the Search Boost value if the field exists.
If you look at the article above, it is tagged as a White Paper. If the user does a search for items that are tagged as an Article / White Papers, then this article wouldn't actually come up in our results because the White Paper GUID is different than its parent. We could dynamically bubble up a Tag
's ancestry at Query time but that would be a little bit of a performance hit, so instead we are going to crawl up the Tag
hierarchy with the crawler. You can see how we are doing this below.
Debugging
When you are setting up your custom crawler and doing some tricky things with searches, you will inevitably need to figure out why-in-the-heck you are not getting the results you are expecting. The best way to do this is to set a break point at the point where your code is about to call RunQuery
and copy the LuceneQuery
value. Once you have this query, you can use the Luke client or Sitecore Rocks VS.NET Plug-in to run the query and see why it is not pulling back what you are expecting.
It's a Wrap
Well, it took four posts, but hopefully you got a good understanding of the approach we used for Filtered Search on a recent project. If you want to learn a bit more, there is a great webcast for the Sitecore Virtual User Group in July that has a great overview and some samples as well. Lucene is quite fast and for future projects, I will probably take it a step further where we can leverage Lucene for more than just Search and Filtered Search and use it for presentation elements as well such as menus, lists and summaries.