Pushing additional information to a document

In this article you will find:

Goal

This article provides information on how to push additional information from a parent type to the document created for the child type when indexing.

Prerequisite

Configured Connector - Configure Hawksearch

Register custom search service - https://bridgeline.atlassian.net/wiki/spaces/CON/pages/3468466897

Create parent-child relation

For the purpose of this article we are going to create two dynamic content types : Festivals which is the parent type and Festival sessions which is the child type. The types have the following fields:

Festival:

  • Title - Short text

  • Description - Short text

  • Venue - Address

Festival Session:

  • Title - Short text

  • StartDate - Date

  • EndDate - Date

Use this .zip with the extracted dynamic types and import them in your Sitefinity instance

You can import the file from Administration → Import/Export menu

Setup Additional fields in Index

The additional fields can be added in two ways:

  • In the advanced section of the index

  • Programmatically

In the advanced section

  1. Open Search indexes in the backend (your-site-domain//Sitefinity/Administration/Search)

2. Open the index and add the additional fields in the Advanced section

 

3. Save the changes

4. You still need to programmatically Update the index. Implement the section Add values to additional fields from bellow.

 

Setup search service

In order to add additional fields programmatically to the index you need to create a custom search service which inherits the HawkseachService class and overrides the CreateIndex and UpdateIndex methods. Please refer to the code snippet below.

Programmatically

using System.Collections.Generic; using System.Linq; using Hawksearch.Search; using Telerik.Sitefinity.Services.Search; namespace SitefinityWebApp.Search { public class CustomSearchService : HawksearchService { private const string ParentTitleFieldName = "ParentTitle"; private const string ParentDescriptionFieldName = "ParentDescription"; private const string ParentVenueFieldName = "ParentVenue"; public override void CreateIndex(string sitefinityIndexName, IEnumerable<IFieldDefinition> fieldDefinitions) { var definitions = fieldDefinitions.ToList(); var parentTitleFieldDefinition = Telerik.Sitefinity.Abstractions.ObjectFactory.Resolve<IFieldDefinition>(); parentTitleFieldDefinition.Name =ParentTitleFieldName; parentTitleFieldDefinition.Type = typeof(string); definitions.Add(parentTitleFieldDefinition); var parentDescriptionFieldDefinition = Telerik.Sitefinity.Abstractions.ObjectFactory.Resolve<IFieldDefinition>(); parentDescriptionFieldDefinition.Name = ParentDescriptionFieldName; parentDescriptionFieldDefinition.Type = typeof(string); definitions.Add(parentDescriptionFieldDefinition); var parentVenueFieldDefinition = Telerik.Sitefinity.Abstractions.ObjectFactory.Resolve<IFieldDefinition>(); parentVenueFieldDefinition.Name = ParentVenueFieldName; parentVenueFieldDefinition.Type = typeof(string); definitions.Add(parentVenueFieldDefinition); base.CreateIndex(sitefinityIndexName, definitions); } } }

 

Add values to additional fields

In the UpdateIndex when we find batch of documents to which we would like to add fields (in our case it’s Festival Session), we simply iterate through them, find both the child and parent items with the help of the manager and then we add the values to the corresponding fields in the document.

using System; using System.Collections.Generic; using System.Linq; using Hawksearch.Search; using Telerik.Sitefinity.DynamicModules; using Telerik.Sitefinity.GenericContent.Model; using Telerik.Sitefinity.GeoLocations.Model; using Telerik.Sitefinity.Model; using Telerik.Sitefinity.Publishing; using Telerik.Sitefinity.Services.Search.Data; using Telerik.Sitefinity.Services.Search.Model; using Telerik.Sitefinity.Services.Search.Publishing; using Telerik.Sitefinity.Utilities.TypeConverters; namespace SitefinityWebApp.Search { public class CustomSearchService : HawksearchService { private const string ParentTitleFieldName = "ParentTitle"; private const string ParentDescriptionFieldName = "ParentDescription"; private const string ParentVenueFieldName = "ParentVenue"; private const string ChildItemType = "Telerik.Sitefinity.DynamicTypes.Model.Festivals.FestivalSession"; public override void UpdateIndex(string name, IEnumerable<IDocument> documents) { var type = string.Empty; var contentType = documents.FirstOrDefault().Fields.FirstOrDefault(f => f.Name == "ContentType"); var documentList = new List<IDocument>(documents); if (contentType != null) { type = contentType.Value.ToString(); } if (string.Equals(type, ChildItemType, StringComparison.InvariantCultureIgnoreCase)) { var dynamicModuleManager = DynamicModuleManager.GetManager(); var childType = TypeResolutionService.ResolveType(ChildItemType); var documentsIds = documents.Select(d => d.Fields.FirstOrDefault(f => f.Name == "Id")?.Value.ToString()).ToList(); var children = dynamicModuleManager.GetDataItems(childType).Where(i => i.Status == ContentLifecycleStatus.Live && documentsIds.Contains(i.Id.ToString())).ToList(); documentList = new List<IDocument>(); foreach (var document in documents) { var fields = new List<IField>(); fields.AddRange(document.Fields); var id = document.Fields.FirstOrDefault(f => f.Name == "Id"); if (id != null) { var documentId = Guid.Empty; if (Guid.TryParse(id.Value.ToString(), out documentId)) { var child = children.FirstOrDefault(i => i.Id == documentId); if (child != null) { var parent = child.SystemParentItem; if (parent != null) { if (parent.GetPropertyValue<Lstring>("Title") != null) { var parentTitleField = new Field { Name = ParentTitleFieldName, Value = parent.GetPropertyValue<Lstring>("Title").Value }; fields.Add(parentTitleField); } if (parent.GetPropertyValue<Lstring>("Description") != null) { var parentDescriptionField = new Field { Name = ParentDescriptionFieldName, Value = parent.GetPropertyValue<Lstring>("Description").Value }; fields.Add(parentDescriptionField); } if (parent.GetPropertyValue<Address>("Venue") != null) { var parentVenueField = new Field { Name = ParentVenueFieldName, Value = parent.GetPropertyValue<Address>("Venue").City }; fields.Add(parentVenueField); } } } } var modifiedDocument = new Document(fields, document.IdentityField.Name); documentList.Add(modifiedDocument); } } } base.UpdateIndex(name, documentList); } } }