在DateTime-range上使用ContentSearch-API查询Sitecore Lucene-index

目前我正在开发一个实施Sitecore 7.0 Update 2的项目

在我的数据模板中,我有一个名为Begin Date的字段和另一个End Date。 这两个字段是使用“日期”(不是日期时间)类型创建的。 因此,当我编辑和创建项目时,它会显示一个日期选择器,并且我已经提交了一些带有虚拟内容的项目以及上个月和当前月份的开始和结束日期。

我想要实现的是获得所选月份内的所有项目。 我的方法包含一个月和一年的整数作为参数。 这应该控制具有从Lucene sitecore_master_index获取的开始日期和结束日期的项目。 Date-field的Sitecore原始值是ISO datetime-strings。

所以这是我试图从所选月份中获取所有项目的查询。

private void GetItems(int month, int year) { using ( IProviderSearchContext context = ContentSearchManager. GetIndex("sitecore_master_index").CreateSearchContext()) { List allEvents = context.GetQueryable(new CultureExecutionContext(Sitecore.Context.Language.CultureInfo)) .Where(s => s.TemplateId == this.EventTemplateID && ((s.BeginDate.Month == month && s.BeginDate.Year == year) || (s.EndDate.Month == month && s.EndDate.Year == year)) ) .ToList(); } } 

使用此Where语句,我希望返回事件模板的所有项目,其中应包含该月份内的日期。 但它返回一个空的结果集。 缺点是我无法调试Lamba表达式,所以不幸的是我不知道该范围的值。 但不是第1年和第9999年之间的事情:)在IQueryable执行查询并返回一些内容之后,列表中的对象包含属性的正确DateTime。 因此它将索引中的字段正确映射到属性。 此外,如果我删除日期检查,只有TemplateID检查是Where子句,它返回结果。 但即使比较BeginDate与DateTime.MinValue和DateTime.MaxValue也不会返回一些东西。

它使用我为此创建的POCO级EvenSearchResultItem。 在这个类中,我已将字段映射到属性,并添加了TypeConverter以将其转换为DateTime。 它至少应该……

 public class EventSearchResultItem : SearchResultItem { [TypeConverter(typeof(IndexFieldDateTimeValueConverter))] [IndexField("__begin_date")] public DateTime BeginDate { get; set; } [TypeConverter(typeof(IndexFieldDateTimeValueConverter))] [IndexField("__end_date")] public DateTime EndDate { get; set; } } 

在Sitecore.ContentSearch.Lucene.DefaultIndexConfiguration.config中我添加了-tag中的字段(也尝试了-tag,但结果没有那么不同)。 看到:

 Begin Date End Date 

因此,在重新索引后,Luke(用于查看Lucene索引内容的Java应用程序)出现该字段并包含该项目的给定日期(在yyyyMMdd> 20140214中)。 就像其他日期字段一样,例如__smallCreatedDate。

我可以通过修改我的查询来解决这个问题:

 List allEvents = context.GetQueryable() .Where(s => (s["Begin Date"].StartsWith(string.Concat(year, month.ToString("00"))) || s["End Date"].StartsWith(string.Concat(year, month.ToString("00")))) ) .ToList(); 

这是Stack Overflow上另一个问题的解决方案。 但我不认为这是最佳实践和可靠。 不幸的是,谷歌没有任何其他选择。 我猜想有什么可能是对的吗?

有没有人有经验从IQueryable过滤DateTime上的Lucene结果? 并且可以指出我正确的方向?

请尝试以下方法:

 private void GetItems(int month, int year) { DateTime startDate = new DateTime(year,month,1); DateTime endDate = new DateTime(year,month, DateTime.DaysInMonth(year, month)); using ( IProviderSearchContext context = ContentSearchManager.GetIndex("sitecore_master_index").CreateSearchContext()) { List allEvents = context.GetQueryable(new CultureExecutionContext(Sitecore.Context.Language.CultureInfo)) .Where(s => s.TemplateId == this.EventTemplateID && ((s.BeginDate >= startDate) || (s.EndDate <= endDate)) ) .ToList(); } } 

编辑:只是解释为什么你的方法不起作用,当lucene索引任何日期字段时,它被索引为数字,格式将为'yyyyMMdd',例如2014年2月18日索引为20140218,所以你可以看到它存储为整数,年,月,日都在同一个字段中,因此您无法与仅年份或月份进行比较等。

现在在Sitecore linq中,如果你想查询日期字段,你必须与'DateTime'类型进行比较,Sitecore知道在将它传递给Lucene之前必须将DateTime对象转换为'yyyyMMdd'格式。

您可以尝试从索引配置和EventSearchResult项中的字段定义中删除下划线。 我以前见过这个问题。

 Begin Date End Date [TypeConverter(typeof(IndexFieldDateTimeValueConverter))] [IndexField("begindate")] public DateTime BeginDate { get; set; } [TypeConverter(typeof(IndexFieldDateTimeValueConverter))] [IndexField("enddate")] public DateTime EndDate { get; set; }