Copied to clipboard

Flag this post as spam?

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


  • Michaël Vanbrabandt 863 posts 3348 karma points c-trib
    Nov 12, 2016 @ 13:20
    Michaël Vanbrabandt
    0

    Deep nested content quering

    Hi all,

    I need some help while quering my content structure.

    Below you can find the structure:

    enter image description here

    So I have a Categorie node that contains primary categories and subcategories.

    Then I have another node called Handelaar which contains companies ( which is presented as a listview ).

    Now, each company has a property called Packages which is a Nested Content data type:

    enter image description here

    There you can see I have a property inside called Category. This is a multinode treepicker which can pick 1 subcategory ( no primary category ).

    Now when I go to a primary category page I need to display all companies which are assigned to one of the primary subcategories.

    Below takes all companies, so I need to extend this query.

    var companyRepo = Model.Content.AncestorOrSelf(1).Children.Where(c => c.IsVisible() && c.DocumentTypeAlias == "companyRepo").First();
    var companies = companyRepo.Children.Where(c => c.IsVisible());
    

    Anyone that can help me out here?

    Thanks in advance

    /Michaël

  • Michaël Vanbrabandt 863 posts 3348 karma points c-trib
    Nov 12, 2016 @ 19:55
    Michaël Vanbrabandt
    0

    Ok,

    after some testing I have come with the following solution.

    I have created a razor extension method which takes the publishedcontent node and all categories:

        public static bool CheckCategories(this IPublishedContent node, int[] categories)
        {
            if(categories.Length > 0)
            {
                var packages = node.GetPropertyValue<IEnumerable<IPublishedContent>>("packages");
    
                bool isElement = false;
                foreach(var package in packages)
                {
                    isElement = categories.Contains(package.GetPropertyValue<int>("category"));
                }
    
                return isElement;
            }
    
            return true;
        }
    

    Then in my view I do:

    // Get all sub categories of current primary category
    var categories = Model.Content.Children.Select(c => c.Id);
    
    // Get company repository node
    var companyRepo = Model.Content.AncestorOrSelf(1).Children.Where(
            c => c.DocumentTypeAlias == "companyRepo"
        ).First();
    
    // Get all companies which are children of one of the sub categories of this primary category
    var companies = companyRepo.Children.Where(c => c.CheckCategories(categories.ToArray()));
    

    Will this be good enough in terms of performance when searching over 250 companies in 30 sub categories? Or should I then use something else?

    /Michaël

  • Marcio Goularte 389 posts 1362 karma points
    Nov 12, 2016 @ 23:18
    Marcio Goularte
    1

    Hi Michaël,

    Your query is complicated! You do not need to pick up the "companyRepo" content and then the children. You can search for docType of company.

    I've never done a query when it has Nested Content, but I believe it works:

        //Get all sub categories of current primary category
        var categories = Model.Content.Children.Select(c => c.Id);
    
        //Get all companies which are children of one of the sub categories of this primary category (Current Content)
                var companies = Umbraco.TypedContentAtXPath("//companyDocType")
                    .Where(c => c.IsVisible() && c.GetPropertyValue<IEnumerable<IPublishedContent>>("packages")
                    .Select(s => s.GetPropertyValue<int>("category")).ContainsAny(categories));
    

    How much performance is a very difficult question. It will depend on several factors, just testing.

  • Michaël Vanbrabandt 863 posts 3348 karma points c-trib
    Nov 13, 2016 @ 07:29
    Michaël Vanbrabandt
    101

    Hi Marcio,

    didn't know about the ContainsAny() was searching for this yesterday.

    Now I have compact the code to just:

        public static bool CheckCategories(this IPublishedContent node, int[] categories)
        {
            if(categories.Length > 0)
            {
                // Nested content property which contains a list of the assigned packages
                var packages = node.GetPropertyValue<IEnumerable<IPublishedContent>>("packages");
    
                return packages.Select(p => p.GetPropertyValue<int>("category")).ContainsAny(categories);
            }
    
            return true;
        }
    

    Kind regards!

    /Michaël

  • Marcio Goularte 389 posts 1362 karma points
    Nov 12, 2016 @ 23:41
    Marcio Goularte
    0

    Suggestion is to create a way to use Relations

    https://our.umbraco.org/documentation/reference/management/services/relationservice

    When a company is published, implement the ContentService.Published method where you take the selected subcategories and creates a relationship between the company and the primary category.

    https://our.umbraco.org/documentation/reference/events/application-startup

    https://our.umbraco.org/documentation/reference/events/contentservice-events

    https://our.umbraco.org/documentation/getting-started/Code/Subscribing-To-Events/

    You would get the companies on the primary category page using the created relation.

    I liked the challenge of your question! I wish I could help more

  • 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