Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • David Amri 214 posts 740 karma points
    Jan 10, 2019 @ 09:06
    David Amri
    1

    Index multi level nested content

    Hi, I'm trying to index multilevel nested content without any success. I'm able to break out the values one level down but as I have multi level nested content the second level writes out the JSON data as one string. Any help would much appreciated.

    The code looks like this:

    using Examine;
    using Umbraco.Core;
    using System.Linq;
    using Newtonsoft.Json;
    using System.Collections.Generic;
    using Newtonsoft.Json.Linq;
    
    namespace Custom.Controllers
    {
        public static class StringExtensions
        {
            public static bool DetectIsJson(this string input)
            {
                input = input.Trim();
    
                if (input.StartsWith("{") && input.EndsWith("}"))
                    return true;
                if (input.StartsWith("["))
                    return input.EndsWith("]");
                else
                    return false;
            }
        }
    
        public class ExamineJsonIndexer : ApplicationEventHandler
        {
            protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
            {
                base.ApplicationStarted(umbracoApplication, applicationContext);
    
                // Declare the indexers that should index JSON properties
                var jsonIndexer = ExamineManager.Instance.IndexProviderCollection["KundUnikumContentIndexer"];
    
                if (jsonIndexer != null)
                {
                    jsonIndexer.GatheringNodeData += (sender, e) =>
                    {
                        // Extract JSON properties
                        var fieldKeys = e.Fields.Keys.ToArray();
    
                        foreach (var key in fieldKeys)
                        {
                            var value = e.Fields[key];
    
                            // Check if index field is JSON data
                            if (value.DetectIsJson())
                            {
                                IndexNestedObject(e.Fields, JsonConvert.DeserializeObject(value), key);
                            }
                        }
                    };
                }
            }
    
            private void IndexNestedObject(Dictionary<string, string> fields, object obj, string prefix)
            {
                var objType = obj.GetType();
    
                if (objType == typeof(JObject))
                {
                    var jObj = obj as JObject;
    
                    if (jObj != null)
                    {
                        foreach (var kvp in jObj)
                        {
                            var propKey = prefix + "___jobject___" + kvp.Key;
                            var valueType = kvp.Value.GetType();
    
                            if (typeof(JContainer).IsAssignableFrom(valueType))
                            {
                                IndexNestedObject(fields, kvp.Value, propKey);
                            }
                            else
                            {
                                fields.Add(propKey, kvp.Value.ToString().StripHtml());
                            }
                        }
                    }
                }
                else if (objType == typeof(JArray))
                {
                    var jArr = obj as JArray;
    
                    if (jArr != null)
                    {
                        for (var i = 0; i < jArr.Count; i++)
                        {
                            var itm = jArr[i];
                            var propKey = prefix + "_jarray_" + i;
                            var valueType = itm.GetType();
    
                            if (typeof(JContainer).IsAssignableFrom(valueType))
                            {
                                IndexNestedObject(fields, itm, propKey);
                            }
                            else
                            {
                                fields.Add(propKey, itm.ToString().StripHtml());
                            }
                        }
                    }
                }
            }
        }
    }
    
  • Hendy Racher 863 posts 3849 karma points MVP 2x admin c-trib
    Jan 10, 2019 @ 09:12
    Hendy Racher
    1

    Hi David,

    You might like to have a look at Look again, it now does this out of the box with a custom Examine indexer/searcher (unfortunately the docs are a little out of date and are being worked on, but happy to help out if I can...)

    Or if you want to roll-your-own, then from this source line might be useful, and the extension method GetFlatDetachedDescendants.

  • David Amri 214 posts 740 karma points
    Jan 10, 2019 @ 09:43
    David Amri
    0

    Hi Hendy, been a long time since the last time :D

    Anyway, how does your code index the json data? I cant find any "json checking" in your code or is this done in some referenced library?

    Best regards David

  • Hendy Racher 863 posts 3849 karma points MVP 2x admin c-trib
    Jan 10, 2019 @ 09:50
    Hendy Racher
    1

    Hi David,

    I think I'm going about it slightly differently - it doesn't parse Json, instead it requests the nested content item as IEnumerable < IPublishedContent > (recursively) and indexes each as a new Lucene document - so the idea is that each nested content item will be indexed in the same way as a regular node - might spark some ideas ?

    Could you do the same kind of thing, avoid JSON parsing, and recurse collections of IPublishedContent to then flatten out then store custom fields on the 'hosting' node ?

  • David Amri 214 posts 740 karma points
    Jan 10, 2019 @ 13:02
    David Amri
    0

    I will try that Hendy. I feel like I'm kind of out of my comfort zone here... but I will certainly try.

    Is there anything more I have to consider except for the links you referred to? Any changes in the examine settings or index?

    Thanks /David

  • David Amri 214 posts 740 karma points
    Jan 11, 2019 @ 13:48
    David Amri
    100

    Found a updated version of Matt Brailsford's snippet that handles nested in nested content.

  • Stefano Beretta 102 posts 247 karma points
    Jun 28, 2019 @ 10:56
    Stefano Beretta
    0

    Hi!

    I successfully use this snippet to index a nested content used by a member, thank you!!!

    Can someone help me to find the code to filter members by a specific property of the nested content?

    Thank you!

    S

  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies