I have a set of courses in a Lucene index, which contain zero or more available dates. I am trying to query the index so that any courses with an available date falling between a From/To date are returned.
The field is being brought back as a collection of DateTime objects using the property within my CourseSearchResultItem
public class CourseSearchResultItem : SearchResultItem
{
[IndexField("availabledatesforcourse")]
public IEnumerable<DateTime> AvailableDatesForCourse { get; set;}
}
The query that is being constructed uses the following code:
if (courseSearchCriteria.FromDate.HasValue)
query = query.Where(c => c.AvailableDatesForCourse.Any(d => d >= courseSearchCriteria.FromDate.Value));
if (courseSearchCriteria.ToDate.HasValue)
query = query.Where(c => c.AvailableDatesForCourse.Any(d => d <= courseSearchCriteria.ToDate.Value));
Running this produces the following exception:
Unsupported lambda in Any call. Expression used 'd => (d >= Value (RCS.Web.Areas.RcsEng.Controllers.CoursesApiController +<>c__DisplayClass10_0).courseSearchCriteria.FromDate.Value)'
I know that this is a result of limitations of the Sitecore.Linq Any() method, but am unsure how to recreate the desired functionality. Has anybody had a similar issue that can shed some light on a solution?
Try the following.
Change your class to look like this:
public class CourseSearchResultItem : SearchResultItem
{
[IgnoreIndexFieldAttribute]
[IndexField("availabledatesforcourse")]
public DateTime AvailableDatesForCourse { get; set;}
}
Now change your query to look like this:
if (courseSearchCriteria.FromDate.HasValue)
query = query.Where(c => c.AvailableDatesForCourse == courseSearchCriteria.FromDate.Value);
if (courseSearchCriteria.ToDate.HasValue)
query = query.Where(c => c.AvailableDatesForCourse == courseSearchCriteria.ToDate.Value));
This sort of syntax works for values that are stored multiple times in a search document (for example, the _path field, which stores the GUIDs of all the parent items separately). It will be translated by the ContentSearch API into a query that Lucene can understand, something like this:
AvailableDatesForCourse:<your date>
Update The [IgnoreIndexFieldAttribute]
will prevent a mapping error when ContentSearch hydrates your class, but will not prevent the field from being used in a query. I wrote a LinqScratchPad Gist to illustrate this, which you can load in the Sitecore LinqScratchPad at /sitecore/admin/LinqScratchPad.aspx, either by pasting it in or using the URL Fetch button. This finds all items that have "Media Item" in the name: