Search code examples
c#.netsitecorelucene.netsitecore7

Sitecore 7 Search Index Issue


I want to restrict the search index in Sitecore 7 to only scan one node of the content tree.

Currently the structure looks like this:

  • sitecore
    • content
      • BaseNode
      • $Company Node

The index is indexing both BaseNode & $Company Node, but I only want it to index $Company Node.

I've updated the default /sitecore/content path in Sitecore.ContentSearch.config, SitecoreContentSearch.Lucene.DefaultIndexConfiguration.config, Sitecore.ContentSearch.Lucene.Index.Master, and Sitecore.ContentSearch.LuceneIndex.Web.config. When I updated the <root> element to point to /sitecore/content/$CompanyNode, I get the following exception when I try to rebuild the indexes.

Any ideas what I need to do to restrict Lucene to just index some items, and not everything?

Exception: System.Reflection.TargetInvocationException 
Message: Exception has been thrown by the target of an invocation. 
Source: mscorlib 
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature         sig, Boolean constructor) 
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[]     parameters, Object[] arguments) 
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr,     Binder binder, Object[] parameters, CultureInfo culture) 
at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters) 
at Sitecore.Configuration.Factory.AssignProperties(Object obj, Object[] properties) 
at Sitecore.Configuration.Factory.AssignProperties(XmlNode configNode, String[]     parameters, Object obj, Boolean assert, Boolean deferred, IFactoryHelper helper) 
at Sitecore.Configuration.Factory.CreateObject(XmlNode configNode, String[] parameters,     Boolean assert, IFactoryHelper helper) 
at Sitecore.Configuration.Factory.GetInnerObject(XmlNode paramNode, String[] parameters,     Boolean assert) 
at Sitecore.Configuration.Factory.AssignProperties(XmlNode configNode, String[] parameters, Object obj, Boolean assert, Boolean deferred, IFactoryHelper helper) 
at Sitecore.Configuration.Factory.CreateObject(XmlNode configNode, String[] parameters, Boolean assert, IFactoryHelper helper) 
at Sitecore.Configuration.Factory.CreateObject(String configPath, String[] parameters, Boolean assert) 
at Sitecore.Search.SearchManager.get_SearchConfiguration() 
at Sitecore.Shell.Applications.Search.RebuildSearchIndex.RebuildSearchIndexForm.GetIndexes() 
at Sitecore.Shell.Applications.Search.RebuildSearchIndex.RebuildSearchIndexForm.BuildIndexes() 

Nested Exception 

Exception: System.InvalidOperationException 
Message: Root item is not defined 
Source: Sitecore.Kernel 
at Sitecore.Diagnostics.Assert.IsNotNull(Object value, String message) 
at Sitecore.Search.Crawlers.DatabaseCrawler.Initialize(Index index) 
at Sitecore.Search.Index.AddCrawler(ICrawler crawler) 

Solution

  • I believe you are attempting to modify the Master Lucene Index file. I believe that would break a lot of things in the end and I would recommend that you create a new Lucene Index file.

    If you were to create a new Index: Place this index in your App_Config / Include Folder

    Sitecore.ContentSearch.Lucene.Index.Alexander.config

    In that config you set the crawler to search for your node.

    <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
      <sitecore>
        <contentSearch>
         <configuration type="Sitecore.ContentSearch.LuceneProvider.LuceneSearchConfiguration, Sitecore.ContentSearch.LuceneProvider">
          <indexes hint="list:AddIndex">
           <index id="alexander_search_index" type="Sitecore.ContentSearch.LuceneProvider.LuceneIndex, Sitecore.ContentSearch.LuceneProvider">
            <param desc="name">$(id)</param>
            <param desc="folder">$(id)</param>
            <!-- This initializes index property store. Id has to be set to the index id -->
            <param desc="propertyStore" ref="contentSearch/databasePropertyStore" param1="$(id)" />
            <strategies hint="list:AddStrategy">
              <!-- NOTE: order of these is controls the execution order -->
              <strategy ref="contentSearch/indexUpdateStrategies/onPublishEndAsync" />
            </strategies>
            <commitPolicy hint="raw:SetCommitPolicy">
              <policy type="Sitecore.ContentSearch.TimeIntervalCommitPolicy, Sitecore.ContentSearch" />
            </commitPolicy>
            <commitPolicyExecutor hint="raw:SetCommitPolicyExecutor">
              <policyExecutor type="Sitecore.ContentSearch.CommitPolicyExecutor, Sitecore.ContentSearch" />
            </commitPolicyExecutor>
            <locations hint="list:AddCrawler">
              <crawler type="Sitecore.ContentSearch.LuceneProvider.Crawlers.DefaultCrawler, Sitecore.ContentSearch.LuceneProvider">
                <Database>web</Database>
                <Root>/sitecore/content/$Company Node</Root>
              </crawler>
            </locations>
           </index>
         </indexes>
       </configuration>
      </contentSearch>
     </sitecore>
    </configuration>
    

    This above index will index everything under that node. In C# you can easily call this with.

    ContentSearchManager.GetIndex("alexander_search_index").Rebuild();
    
    using (var searchContext = ContentSearchManager.GetIndex("alexander_search_index").CreateSearchContext())
       {
           var result = searchContext.GetQueryable<SearchResultItem>()
               .Where(//Put Query Here);
    
           //do ForEach if you return multiple and so on.
    
           if (result != null)
                  Context.Item = result.GetItem();
       }
    

    You can also Rebuild your indexes and verify that they are working by going into Sitecore -> Control Panel -> Indexing -> Indexing Manager. After doing that you should see the Index.

    Another Edit: You could also just perform your C# Search underneath that item in the content tree and use only the web database.

     Item bucketItem = //Code to get $Company Node as a Sitecore Item
      //Probably Sitecore.Context.Database.GetItem("Guid for $Company Node")
    
     using (var searchContext = ContentSearchManager.GetIndex(bucketItem as      IIndexable).CreateSearchContext())
      {
         try
         {
              var result = searchContext.GetQueryable<SearchResultItem>().Where(x => x.Name == itemName).FirstOrDefault();
                 if (result != null)
                     Context.Item = result.GetItem();
         }
         catch (Exception)
         {
             //Do something
         }
      }