Many Sitecore developers these days use the Advanced Database Crawler (ADC) as their interface into the Lucene.NET world. The ADC is a great tool because it builds on top of the
Sitecore.Search namespace which in its own right wraps over Lucene.NET. Many Sitecore instances will contain multiple sites and share data across them. Sometimes its necessary to build a site-specific search mechanism that functionally works the same for each site, but ensures results are only for the given site. This blog post will go over two simple ways to accomplish this with the Advanced Database Crawler.
The easiest way to accomplish this task to filter results by a managed site is to use the
LocationIds filter on the search parameter object. This location filter will only return
SkinnyItem results that fall at or under the provided location. The
LocationIds also happens to be a delimited list of GUIDs, so we can easily leverage this to filter results by site:
- Get the context site path
- Filter with the ADC using
LocationIdsby passing the home page’s or site root’s GUID
For example, here’s some basic code to do just that:
Item homeItem = Sitecore.Context.Database.GetItem(Sitecore.Context.Site.StartPath);
if(homeItem != null)
searchParams.LocationIds = homeItem.ID.ToString();
This example assumes your home page is below the site root path, which is common if you have some other data items for your site that are not pages.
Full Path Dynamic Field
Another way to do the same type of operation takes a bit more work and doesn’t necessarily yield any better results, however it’s good to have options! This approach requires to you define a dynamic field in your index for the full path of each item. If you’re using v1 of the ADC, this exists as the “_fullcontentpath” dynamic field. If you’re using the ADC v2, you’ll need to define it (grab it from here).
Once you configure that dynamic field, simply write some code to compare the skinny items from a search operation based on the full path vs. the context site’s start path. Here’s an example:
public static IEnumerable<SkinnyItem> FilterSkinnyItemsByContextSite(IEnumerable<SkinnyItem> items)
return FilterSkinnyItemsBySite(items, Sitecore.Context.Site);
public static IEnumerable<SkinnyItem> FilterSkinnyItemsBySite(IEnumerable<SkinnyItem> items, Sitecore.Sites.SiteContext site)
return FilterSkinnyItemsByRootPath(items, site.RootPath);
public static IEnumerable<SkinnyItem> FilterSkinnyItemsByRootPath(IEnumerable<SkinnyItem> items, string siteRootPath)
// isolate the path query to a finite item path, not a prefix of a longer path
// e.g. ensures a filter on /sitecore/content/brand as /sitecore/content/brand/ to avoid allowing /sitecore/content/brand2
siteRootPath = siteRootPath + "/";
return items.Where(si => si.Fields["_fullcontentpath"].StartsWith(siteRootPath, StringComparison.InvariantCultureIgnoreCase));
As I said before, leveraging the
LocationIds filter at the search-level is easier and more efficient as it won’t return unnecessary results. The second approach is good if you have existing search code that you don’t want to adjust too much and instead want to easily filter the results by site.