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. Today, we are going to look at the service layer that is called by the presentation layer.
Here, we have the method signature that is called by the client. So as we went over in Part 1, if the user searches for "cost savings" and selects the Industries of "Construction" and "Energy", the following URL is used in the Ajax call on the client end.
This URL ends up calling the
SearchInsightsJson method within the
SearchService web service class and it will pass in the
GUIDs associated with Construction and Energy, the current page the user is on, the results the client wants per page the
searchString is set to "cost savings".
You will notice the method has two attributes that mark the method as an
OperationContract (available via the web service) and the
WebGet attribute is stating that the response should be in a JSON format.
Prevent Client-side Caching
The three lines of code above help prevent any caching that may occur by the client. Technically because the URL would be unique for each search request, we could remove this block of code altogether with little impact but this ensures if a new item has been published since the client ran the query that it would get picked up in the search results.
Building-up the Criteria
The code above shows the approach to calling the Search service. We are populating a
SearchParam object with the information needed by the Search Service to run the query.
LocationIds = The top folder or folders within the CMS we want to search
TemplateIds = The page types we want included in our search
FullTextQuery = The key word or phrase the user entered in the search form
ShowAllVersions = This specifies if we want to search all versions of a page or just the latest.
Language = Sets the language context of our search (for multi-lingual sites)
We then check each
Category parameter and if it is not
null, we will add the pipe delimited
GUIDs to the
Search Call and Setup Paging
The first piece is calling our Search Service and passing in our Criteria. We can then set some parameter values that we will include in our JSON result so our presentation can provide paging functionality without having to do the logic on their end.
We set the
TotalResults to the
hits.Count and the
CurrentPage is the page that was passed in originally so the client doesn't have maintain state.
The results we get back from the Search Service is actually just a
List of what we are calling a
SkinnyItem, that is to say, it is just a pointer to the actual
Item along with some other meta data.
SkinnyItem has a
GetItem() method that will retrieve the full
Item from Sitecore but if we have 1000+ items that match our search and we truly only need to fetch the ones that are being displayed on the current page (8 of them), it would be a lot of unnecessary overhead to do this.
We end up creating an s and an e variable that we will use in the next code snippet. e is either going to be (
perPage * page) or the total results from the search whichever is less. s is either (
(perPage * page) - perPage) or the
hits.Count - perPage whichever is less (as long as it is
Above, we are iterating through the
SkinnyItems between our s and or e count and grabbing the full Item out of
Sitecore in order to populate a
SearchResultItem and add it to our
resultItems collection. This seems like an extra step because we are going from a
SkinnyItem to get a
Sitecore Item to get a
SearchResultItem but there is a logical reason. The
SkinnyItem is essentially a representation of the raw search result from Lucene. The
Sitecore Item is acting as full data record or
Domain Object and the
SearchResultItem is a simple Data Transfer Object containing only the fields needed by the view.
We set the JSON
resultData.Results equal to the collection of
SearchResultItems we just created and we set the
TotalPages equal to the total records divided by items per page and round up.
We set the
SearchUrl with the value that was passed in and provide it back to the client so it doesn't have to worry about state.
PageStart is what the starting page in the page navigation should be. This is hard coded right now with a paging of 5 but this could come from a config file or even the CMS. This allows our client to setup paging of 6 through 10 when a current page of 7 is passed in (see below).
So that is what our web service looks like. While writing this blog post and taking screenshots, I see some areas of improvement and refactoring but you should get the idea of what the service layer should be doing. Part 4 will focus on our actual Search service. This will go into detail about how we customized our Crawler, setup our Indexes and leveraged the advanced searcher / crawler from the
Sitecore Shared Source library - if you want to get a headstart on that, I recommend this video.
Permalink | Leave a comment »