Sitecore Search by Site with the Advanced Database Crawler

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.

Location Filter

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:

  1. Get the context site path
  2. Filter with the ADC using LocationIds by 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
    if (!siteRootPath.EndsWith("/"))
        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.

Posted in Sitecore
2 comments on “Sitecore Search by Site with the Advanced Database Crawler
  1. I would like to index the full path, but where exactly do I put the code snippet you give that defines FullPathField?

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>