5

Sitecore indexing works great for simple indexing scenario's, as the main working entity is a sitecore item. With computed fields you can add custom logic and fields for a record. But I have 2 more advanced scenario's and wonder how to implement those:

1) I have item A and another item B. I don't want to index them separately, but as 1 document. So if Sitecore is indexing A, then it should merge the fields of Item A with those of item B (with possible renamings) and create 1 document in the index. (I realize that computed fields may be used here, but that becomes bulky and is not very elegant)

2) I have item A and I do want to create 2 documents in the index, originating from Item A. The two documents will get their fields from other items in the content tree and be combined with the fields of A.

Any ideas?

  • are item A and B created using the same template? – adarsh May 29 '17 at 6:05
  • No, they are created from different templates – staccata Jun 6 '17 at 17:30
  • As Zachary suggested, I would have told you to use computed index fields. – adarsh Jun 6 '17 at 17:51
10

From your description, it looks like you have run into the same predicament that all Sitecore developers inevitably run into with regard to Content Search indexing: why don't my data source items just index with the item for the page that they display on? Of course, this question doesn't just apply to data source items and the item for the page that they display on, but that is a valid, real-life example of this situation.

The answer is that, unfortunately, the indexing technology out of the box isn't quite on par with the more atomic architecture of splitting data into multiple templates and re-merging them together after using Presentation Details. There are some ways for you to get around this, however:

  1. Computed Index Fields - Traditional Use: I read your question, and I know you're aware of them, but I have to say them. They do get clunky, and it's painful to need to create a separate one for every field. However, you could index all text-based content from item B in a single CIF on item A, should you so choose. CIFs do not have to be complex. You could write an abstract base class that does all of the work and simply have each implementing class pass the field name/ID to a method that identifies the field on item B that you wish to index. You could even do this with a single class that uses a custom constructor to read from a custom attribute in the configuration that identifies the field to be indexed (and maybe even the item or how to search for the item via an enum, like AncestorSearch, ChildSearch, DescendantSearch, etc).
  2. Computed Index Fields - Merging Like Documents: This really isn't different from the traditional use of CIFs, but if your goal is to take Item A and Item B, both of which inherit from the same template, and index them as the same document without adding any new fields then you can use one CIF per field on the template and the values from both items will be added to the same fields on the resulting document. Both Solr and Lucene append additional values for an existing field to the exising field, rather than creating new fields. This may, however, result in some unexpected results in your boosting.
  3. Custom Search Provider: This step is more work and adds more risk, since Sitecore supports the native providers but you would have to support your custom one, but it is doable. If you write your own search provider, you could write your own implementation for creating relationships between items that should be indexed together. IMHO, this feature should be native with Sitecore and will hopefully come in a future version (or at least support for being able to tap into code points that let us add this functionality ourselves). Currently, however, there is no way to do this in the system without writing your own provider.
  4. Dynamic Search Configuration: This is something that I have started to experiment with recently, since Sitecore has exposed the Sitecore.Configuration.ConfigReader.LoadAutoIncludeFiles methods for override. This implementation is a bit more complex, but it is, IMHO, lower effort than creating a custom provider, and it leaves the responsibility of supporting your search and indexing implementation up to Sitecore, rather than taking it on yourself. Basically, what you need to do is create a T4 template (or similar tool) for generating Computed Index Field config entries and then write a custom implementation for configuring the relationships between items that should be indexed together (i.e. between items A and B or between templates, etc.). On initialize, the Sitecore.Configuration.ConfigReader.LoadAutoIncludeFiles method would be called, which would in turn call a custom method to retrieve these relationships and generate all of the necessary entries for each relationship. The issue that you will likely come across is that you will need to create the class(es) for the CIFs ahead of time. At this point, you need to know the field name/ID that the CIF should index. One option would be to use the FieldName property, which holds the name of the field that was set in the configuration, thus mandating that this field name be consistent with what is in Sitecore. Another, and IMHO better solution could be to have your T4 template (or other generation mechanism) add a custom attribute to your CIF config entry that contains the name/ID of the field to index. You would then write a constructor for your CIF class, like the one below, and you would need only to read the "SitecoreFieldIdentifier" property to know the field to index in the CIF. Beyond that, the rest is left up to how you chose to implement the relationship management. My recommendation would be to have a thread-safe mapping between the index-field name and the item that the Sitecore Field to be indexed lives on. There are many other options though. One additional thing to note is that this implementation is likely to slow your instance's initialization time down based on how many indexing relationships your solution supports.

Constructor for DynamicComputedIndexField:

 public abstract class DynamicComputedIndexField : AbstractComputedIndexField
 {
     public virtual string SitecoreFieldIdentifier { get; set; }

     protected DynamicComputedIndexField(XmlNode configNode) : base(configNode)
     {
         SitecoreFieldIdentifier = XmlUtil.GetAttribute("sitecoreFieldIdentifier", configNode);
     }

     ...
 }
  • Wow, thats quite an extensive answer. Thanks! – staccata Jun 1 '17 at 20:53
  • No problem, at all. If you go the dynamic configuration route and have any trouble implementing feel free to reach out to me over Sitecore Community Slack (@zachary_kniebel) – Zachary Kniebel Jun 1 '17 at 20:56
3

If you're trying to include multiple fields from another document, I'd argue that the best integration point would be to provide a custom document builder (extending LuceneDocumentBuilder / SolrDocumentBuilder) and overriding AddItemFields().

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.