Reputation: 176
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?
Upvotes: 3
Views: 1149
Reputation: 67
I ran into this same issue and followed Dan's steps which got me part of the way to a solution. The issue I was having was that SitecoreContentSearch was creating a query that Solr couldn't parse. I updated the linq query to this:
if (courseSearchCriteria.FromDate.HasValue && courseSearchCriteria.ToDate.HasValue)
query= query.Where(x => x.AvailableDatesForCourse.Between(courseSearchCriteria.FromDate.Value,courseSearchCriteria.ToDate.Value,Inclusion.Both));
This should create a query that looks like this :
availabledatesforcourse:[2018-07-13T15:48:42.975Z TO 2021-07-13T15:48:43.023Z]
This allows me to search a list of dates for any value that falls into this range.
Upvotes: 0
Reputation: 3154
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:
Upvotes: 5