Complex Find sorting

Vote:
 

I have some difficulties in doing the sorting in Find.

I have the following structure:

class TimeBlock
{
DateTime StartDate
}

class Event
{
ContentArea Times
}

The goal is to sort events by closest future (more than DateTime.Now + x hours) StartDate of their TimeBlocks.

I tried to index all StartDates like this:

[Ignore]
        public virtual DateTime[] StartDates
        {
            get
            {
                var dates = Times?.FilteredItems
                  ?.Select(x => x.GetContent())
                  .Where(b => b != null)
                  .OfType()
                  .DefaultIfEmpty(new CourseInfoBlock { StartDate = DateTime.MinValue })
                  .Select(x => x.StartDate).ToArray()
                  ?? new[] { DateTime.MinValue };
                return dates;
            }
        }



and then do the ordering

Find.Search().Filter.....
.OrderBy(p => p.StartDates, p => p, p => p.GreaterThan(hideBeforeDate), SortMissing.Last, SortOrder.Ascending, SortMode.Min



but I get an exception “No mapping found for [StartDates.$$date] in order to sort on”

I'll be grateful for any help.

#171747
Nov 17, 2016 10:25
Vote:
 

You will need a client convention right?

//using EPiServer.Find.ClientConventions;
 
client.Conventions.ForInstancesOf<Event>()
    .IncludeField(x => x.StartDates);
#171748
Edited, Nov 17, 2016 10:44
Vote:
 

Can you check the index and verify that StartDate is part of the index? (ref the Ignore attribute on your property).

#171750
Nov 17, 2016 10:59
Vote:
 

Yes, I have StartDates of my events indexed

"StartDates": [
        "2016-12-10T03:00:00Z",
        "2016-11-11T11:00:00Z",
        "2016-11-15T17:00:00Z"
    ],
#171751
Nov 17, 2016 11:44
Vote:
 

Maybe new extension with GetClosestStartDate() on event class that returns a single start date and index that instead?

#171753
Nov 17, 2016 12:20
Vote:
 

Hi Daniel,

I cannot do that because ClosestDate on the time of indexing may be different than the closest date on the time of querying.

#171755
Nov 17, 2016 12:54
Vote:
 

My final solution is:

1. Add NestedConvention in initialization module:

SearchClient.Instance.Conventions.NestedConventions.ForInstancesOf<Event>().Add(t => t.StartDatesForIndexing);

2. Create custom class because you signature for Add method is

Expression<Func<TSource, IEnumerable<TListItem>>> expr) where TListItem : class;

my custom class:

 [JsonObject]
    public class DateIndexCustom
    {
        [JsonProperty]
        public DateTime StartDateForIndexing { get; set; }
    }

and property in Event class:

 [Ignore]
        public virtual DateIndexCustom[] StartDatesForIndexing
        {
            get
            {
                var dates = Times?.FilteredItems
                  ?.Select(x => x.GetContent())
                  .Where(b => b != null)
                  .OfType<EventInfoBaseBlock>()
                  .DefaultIfEmpty(new CourseInfoBlock { StartDate = DateTime.MinValue })
                  .Select(x => new DateIndexCustom { StartDateForIndexing = x.StartDate }).ToArray()
                  ?? new[] { new DateIndexCustom { StartDateForIndexing = DateTime.MinValue } };
                return dates;
            }
        }

3. query looks similar to my initial one:

query = query.OrderBy(d => d.StartDatesForIndexing, st => st.StartDateForIndexing, st => st.StartDateForIndexing.GreaterThan(hideBefore));

4. I reindexed all content

#172356
Edited, Dec 01, 2016 9:35
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.