Copied to clipboard

Flag this post as spam?

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


  • Dan Sharpe 8 posts 88 karma points
    Mar 17, 2017 @ 15:36
    Dan Sharpe
    0

    Querying Child Content

    so basically, i'm new to umbraco, i have a document type of Demo, it has a a property of demoDate.

    as the client wishes these to be shown in a calendar, i only want to get the demo's between a certain date range, using an API controller. i've had a few stabs at it, but basically i cant get the filter to work on the date range, here is my class:

    public class DemosController : UmbracoApiController
    {
        public IEnumerable<Demo> GetDemos(DateTime startdate, DateTime enddate)
        {
             var demosPage = Umbraco.ContentAtRoot().First().Children("demosHome").Where("Visible").First();
            IPublishedContent typePage = Umbraco.TypedContent(demosPage.Id);
            var typedChildren = typePage.Children.Where(c => (DateTime)c.GetProperty("demoDate").Value <= enddate).ToList();
            DynamicPublishedContentList demos =    Umbraco.Content(demosPage.Id).Children("demo").Where("Visible").Where("demoDate <= @0", enddate).OrderBy("demoDate");
            //.Where($"demoDate <= {enddate.ToShortDateString()}")
            //.Where($"demoDate <= {enddate}")
    
            // a.
            return typedChildren
                //.Cast<DynamicPublishedContent>()
                .Select(d => new Demo { Date = Convert.ToDateTime(d.GetProperty("demoDate").Value), Title = (string)d.GetProperty("demoTitle").Value, Url = d.Url })
                .ToList();
        }
    
        public string Test()
        {
            return "test";
        }
    }
    

    to test it im simply doing this at the minute:

    <button>Click</button><script type="text/javascript">
    var startdate = '2016/03/01';
    var enddate = '2016/03/31';
    $(document).ready(function () {
        $("button").click(function () {
            $.get('@url', { startdate: startdate, enddate: enddate }, function (data, status) {
                alert(data);
            });
        });
    })
    

    i'm wondering if someone could tell me a way to get it to work, if i try and compare them through the dynamic way i get an error saying >= cannot be applied to types of string.

    any help would be greatly appreciated

    thanks in advance

  • Marc Goodson 2157 posts 14432 karma points MVP 9x c-trib
    Mar 18, 2017 @ 09:10
    Marc Goodson
    0

    Hi Dan

    Try this:

    public class DemosController : UmbracoApiController
    {
        public IEnumerable<Demo> GetDemos(DateTime startdate, DateTime enddate)
        {
            // first lets get the demospage node
            // umbraco has a typed (or dynamic version) helper that enables you to get the first node at a particular XPATH
            //so 'Home' is the document type of your root node
            var demosPage = Umbraco.TypedContentSingleAtXPath("//Home/demosHome");
            // then lets get the children of the demosPage with doctype alias demoPage ?
            // then we use strongly typed where filtering to do apply the date conditions
            // .GetPropertyValue<DateTime("alias") will do the date conversion for you
            var demos = demosPage.Children(new string[] { "demoPage" }).Where(f => f.GetPropertyValue<DateTime>("demoDate") > startdate && f.GetPropertyValue<DateTime>("demoDate") <= enddate).OrderByDescending(f=>f.GetPropertyValue<DateTime>("demoDate"));
            // as before select the result into a plain Demo class for the Web API to serialise
            return demos.Select(d => new Demo { Date = d.GetPropertyValue<DateTime>("demoDate"), Title = d.GetPropertyValue<string>("demoTitle"), Url = d.Url })
                .ToList();
        }
    
        public string Test()
        {
            return "test";
        }
    }
    public class Demo
    {
        public DateTime Date { get; set; }
        public string Title { get; set; }
        public string Url { get; set; }
    }
    
  • Damiaan 442 posts 1302 karma points MVP 6x c-trib
    Mar 18, 2017 @ 12:39
    Damiaan
    0

    Marc's solution With the GetPropertyValue<DateTime> is the best. However, if you have LOTS of documents, do know that you are getting each document and the filter it afterwards. If you experience a performance impact, consider other querying ways like an examine query...

  • Dan Sharpe 8 posts 88 karma points
    Mar 20, 2017 @ 08:12
    Dan Sharpe
    0

    Hi Damiaan,

    with reference to your comment, is it getting all the documents because of the .Children(new string[] { "demoPage" }) part of the query?

    is there anyway to minimize this result set within this query structure or is examine the only way to do this?

    thanks

  • Marc Goodson 2157 posts 14432 karma points MVP 9x c-trib
    Mar 20, 2017 @ 22:34
    Marc Goodson
    100

    Hi Dan

    Yes it's all about context, the best idea is to start off simple, get something working and then measure the performance with the MiniProfiler

    eg

        var profiler = UmbracoContext.Application.ProfilingLogger;
        using (profiler.DebugDuration<YourClass>("Name of what you are measuring"))
        {   
    // code you want to measure the performance of
            System.Threading.Thread.Sleep(1000);
        }
    

    then depending on the context of your application you may need to refactor if performance is an issue.

    For example in the code above, instead of retrieving the demo page with

    var demosPage = `Umbraco.TypedContentSingleAtXPath("//Home/demosHome");`
    

    and then filtering in memory by dates:

     var demos = demosPage.Children(new string[] { "demoPage" }).Where(f => f.GetPropertyValue<DateTime>("demoDate") > startdate && f.GetPropertyValue<DateTime>("demoDate") <= enddate).OrderByDescending(f=>f.GetPropertyValue<DateTime>("demoDate"));
    

    You could more efficiently retrieve all the demos between the two dates, still using the Umbraco Cache with a single XPath statement, and then no filtering will take place in memory!

    eg:

    var demos = Umbraco.TypedContentAtXPath("//Home/demosHome/demoPage[@isDoc and number(translate(demoDate,'-T:','')) < '" + String.Format("{0:yyyyMMddHHmmss}",enddate) + "' and number(translate(demoDate,'-T:','')) > '" + String.Format("{0:yyyyMMddHHmmss}", startdate) + "']");
    

    XPath against XML is really quick.

    But you can't be really sure, without measuring, because the best approach will be determined by whether there is 10, 100, or 100000 demos

    I've found the Umbraco Cache can perform pretty well compared to Examine for this kind of query for surprisingly large recordsets, but if you were doing a fuzzy search of text, examine is the obvious way to go!

    (Also if you have 100000 demos - Umbraco content may not be the best way of storing them)

    regards

    Marc

  • Dan Sharpe 8 posts 88 karma points
    Mar 21, 2017 @ 15:36
    Dan Sharpe
    0

    thanks for the replies and help with this one guys, plenty to think about in terms of performance etc.

    i also got the xpath query working now with great help to Marc, my xpath skills are so hot (yet), so onto making the next bit work

    thanks again for the help

Please Sign in or register to post replies

Write your reply to:

Draft