Copied to clipboard

Flag this post as spam?

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


  • Bjarne Fyrstenborg 1284 posts 4038 karma points MVP 8x c-trib
    Apr 20, 2021 @ 18:07
    Bjarne Fyrstenborg
    0

    Examine search nodes with data from children

    Hi..

    I have a use-case where I have some BrandPage nodes, which has a training archive as child node. In this archive some training nodes will be created via a form.

    A specific member type has then access to from frontend the mark these training nodes as completed. Basically it just set the value of a property to 1 using boolean datatype.

    I can search the BrandPage nodes using Examine using the following:

    public class BrandSurfaceController : SurfaceController
    {
        private readonly IExamineManager _examineManager;
        private readonly IUmbracoContextAccessor _umbracoContextAccessor;
    
        public BrandSurfaceController(IExamineManager examineManager, IUmbracoContextAccessor umbracoContextAccessor)
        {
            _examineManager = examineManager;
            _umbracoContextAccessor = umbracoContextAccessor;
        }
    
        [ChildActionOnly]
        public ActionResult BrandList(int p = 1, int ps = 50)
        {
            return PartialView("PagedBrandList", GetPagedBrands(p, ps));
        }
    
        private PagedResult<BrandPage> GetPagedBrands(int page, int pageSize)
        {
            if (_examineManager.TryGetIndex(Constants.UmbracoIndexes.ExternalIndexName, out var index))
            {
                var searcher = index.GetSearcher();
                var query = searcher.CreateQuery()
                    .GroupedOr(new[] { "__NodeTypeAlias" }, new[] {
                        BrandPage.ModelTypeAlias
                    });
    
                var results = query.OrderBy(new SortableField("name", SortType.String)).Execute(pageSize * page);
                var totalResults = results.TotalItemCount;
                var pagedResults = results.Skip(pageSize * (page - 1));
    
                var items = pagedResults.ToPublishedSearchResults(_umbracoContextAccessor.UmbracoContext.Content)
                    .Select(x => x.Content)
                    .OfType<BrandPage>()
                    .OrderBy(x => x.SortOrder);
    
                return new PagedResult<BrandPage>(totalResults, page, pageSize)
                {
                    Items = items
                };
            }
    
            return new PagedResult<BrandPage>(0, page, pageSize);
        }
    }
    

    At some point e.g. a BrandPage could then have 4/5 trainings marked as completed, other could have 5/5 or 10/10.

    My question is then how to filter brand which does not have completed all trainings. e.g 2/5 or 8/10.

    I can imagine a few approaches, but maybe there is a better way to handle this:

    1. A second Examine search query filtering training nodes and joining the results with the brand page results.

    2. Using TransformingIndexValues event to index the number of completed training nodes in a new field. However when a new training node is created or marked as completed it would require to re-index the result of the training node.

    /Bjarne

  • Nik 1614 posts 7260 karma points MVP 7x c-trib
    Apr 20, 2021 @ 21:32
    Nik
    0

    Hey Bjarne,

    If it was me, I'd go with your second option because Examine doesn't lend itself to what I would call "conditional" searching like that. So when a new training node is created (saved/published) you could tell examine to explicitly re-index it's parent.

    A third option is to store the "Completed" status in a custom DB table and then search that instead. The table could be as basic as:

    Brand, Training, Completed
    

    Then you could search for any distinct Brand where Completed = false.

    You could cache the results as well to reduce DB hits.

    Just an alternative :-)

    Nik

Please Sign in or register to post replies

Write your reply to:

Draft