目前我正在开发一个实施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<EventSearchResultItem> allEvents = context.GetQueryable<EventSearchResultItem>(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,但结果没有那么不同)。 参见:
<field luceneName="__begin_date" storageType="yes" indexType="tokenized" format="yyyyMMdd">Begin Date</field>
<field luceneName="__end_date" storageType="yes" indexType="tokenized" format="yyyyMMdd">End Date</field>
因此,在重新索引后,Luke(用于查看Lucene索引内容的Java应用程序)字段出现并包含该项目的给定日期(在yyyyMMdd&gt; 20140214中)。就像其他日期字段一样,例如__smallCreatedDate。
我可以通过将查询修改为:
来解决此问题List<EventSearchResultItem> allEvents = context.GetQueryable<EventSearchResultItem>()
.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结果?并且可以指出我正确的方向?
答案 0 :(得分:6)
尝试以下方法:
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<EventSearchResultItem> allEvents = context.GetQueryable<EventSearchResultItem>(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知道必须将DateTime对象转换为'yyyyMMdd'格式才能将其传递给Lucene。
答案 1 :(得分:0)
您可以尝试从索引配置和EventSearchResult项中的字段定义中删除下划线。我以前见过这个问题。
<field luceneName="begindate" storageType="yes" indexType="tokenized" format="yyyyMMdd">Begin Date</field>
<field luceneName="enddate" storageType="yes" indexType="tokenized" format="yyyyMMdd">End Date</field>
[TypeConverter(typeof(IndexFieldDateTimeValueConverter))]
[IndexField("begindate")]
public DateTime BeginDate { get; set; }
[TypeConverter(typeof(IndexFieldDateTimeValueConverter))]
[IndexField("enddate")]
public DateTime EndDate { get; set; }