Skip to content

Instantly share code, notes, and snippets.

@robertjf
Last active January 11, 2019 08:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robertjf/2177e28ae586eef94225bcd57317ff26 to your computer and use it in GitHub Desktop.
Save robertjf/2177e28ae586eef94225bcd57317ff26 to your computer and use it in GitHub Desktop.
Extract and index properties from StackedContent or NestedContent and aggregate them to a single indexed field. Umbraco v7
using Examine;
using Examine.Providers;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Linq;
using System.Text;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.PropertyEditors;
using Umbraco.Web;
using UmbracoExamine;
namespace YourITTeam.Core.EventHandlers
{
public class ExamineIndexer : ApplicationEventHandler
{
protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
foreach (var provider in ExamineManager.Instance.IndexProviderCollection.AsEnumerable<BaseIndexProvider>())
{
if (provider.Name.StartsWith("Internal"))
{
continue;
}
provider.GatheringNodeData += provider_GatheringNodeData;
}
}
void provider_GatheringNodeData(object sender, IndexingNodeDataEventArgs e)
{
if (e.IndexType == IndexTypes.Content)
{
var node = ApplicationContext.Current.Services.ContentService.GetById(e.NodeId);
AggregateFields(e, node, "_title", new[] {
"pageTitle",
"subTitle"
});
AggregateFields(e, node, "_content", new[] {
"bodyContent",
"detail",
"extract",
"description",
"introduction",
"quote",
"heading",
"body",
});
}
}
/// <summary>
/// Munge the fields into a new one identified by key for searching.
/// </summary>
/// <param name="e"></param>
/// <param name="node"></param>
/// <param name="key"></param>
/// <param name="fields"></param>
private void AggregateFields(IndexingNodeDataEventArgs e, IContentBase node, string key, string[] fields)
{
var combinedFields = new StringBuilder();
foreach (var prop in node.PropertyTypes.Where(p => fields.Contains(p.Alias)))
{
switch (prop.PropertyEditorAlias)
{
// We want to attempt to retrieve the relevant fields from the properties that return JSON content.
case Constants.PropertyEditors.NestedContentAlias:
case "Our.Umbraco.StackedContent":
{
var editor = PropertyEditorResolver.Current.GetByAlias(prop.PropertyEditorAlias).ValueEditor;
var nestedJson = editor.ConvertDbToEditor(node.Properties.Single(p => p.Alias == prop.Alias),
prop,
ApplicationContext.Current.Services.DataTypeService) as JToken;
combinedFields.AppendLine(IndexNestedJObject(nestedJson, fields));
break;
}
case Constants.PropertyEditors.GridAlias:
{
var editor = PropertyEditorResolver.Current.GetByAlias(prop.PropertyEditorAlias).ValueEditor;
var gridJson = editor.ConvertDbToEditor(node.Properties.Single(p => p.Alias == prop.Alias),
prop,
ApplicationContext.Current.Services.DataTypeService) as JToken;
// We only want a selection of the properties from the grid...
combinedFields.AppendLine(IndexNestedJObject(gridJson, new[] { "value", "caption" }));
break;
}
default:
combinedFields.AppendLine(node.GetValue<string>(prop.Alias));
break;
}
}
e.Fields.Add(key, combinedFields.ToString());
}
/// <summary>
/// Index the properties in a JToken object and return as a combined string
/// </summary>
/// <param name="token"></param>
/// <param name="targetedFields">list of fields to extract data from - extracts all if null.</param>
/// <returns></returns>
private string IndexNestedJObject(JToken token, string[] targetedFields = null)
{
StringBuilder combined = new StringBuilder();
if (token is JArray jArr)
{
foreach (var item in jArr)
{
combined.AppendLine(IndexNestedJObject(item, targetedFields));
}
}
if (token is JObject jObj)
{
foreach (var kvp in jObj)
{
if (kvp.Value is JArray || kvp.Value is JObject)
{
combined.AppendLine(IndexNestedJObject(kvp.Value, targetedFields));
}
else if ((targetedFields != null && targetedFields.Contains(kvp.Key)) || targetedFields == null)
{
combined.AppendLine(kvp.Value.ToString());
}
}
}
return combined.ToString();
}
}
}
@DavidVonAmri
Copy link

Hi,

I'm getting intellisense errors on these lines "if (token is JArray JArr)" and "if (token is JObject jObj)" in the IndexNestedJObject metod.
The name 'JArr' and 'JObj' does not exists in the current context? Any ideas why this is happening?

Cheers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment