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
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);
}
}
}