Tho*_*man 3 .net c# linq sitecore
目前我正在开发一个实施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();
}
}
Run Code Online (Sandbox Code Playgroud)
使用此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; }
}
Run Code Online (Sandbox Code Playgroud)
在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>
Run Code Online (Sandbox Code Playgroud)
因此,在重新索引后,Luke(用于查看Lucene索引内容的Java应用程序)出现该字段并包含该项目的给定日期(在yyyyMMdd> 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();
Run Code Online (Sandbox Code Playgroud)
这是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<EventSearchResultItem> allEvents = context.GetQueryable<EventSearchResultItem>(new CultureExecutionContext(Sitecore.Context.Language.CultureInfo))
.Where(s =>
s.TemplateId == this.EventTemplateID &&
((s.BeginDate >= startDate) || (s.EndDate <= endDate))
)
.ToList();
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:只是解释为什么你的方法不起作用,当lucene索引任何日期字段时,它被索引为数字,格式将是'yyyyMMdd',例如2014年2月18日被索引为20140218,所以你可以看到它存储为整数,年,月,日都在同一个字段中,因此您无法与仅年份或月份进行比较等.
现在在Sitecore linq中,如果你想查询日期字段,你必须与'DateTime'类型进行比较,Sitecore知道在将它传递给Lucene之前必须将DateTime对象转换为'yyyyMMdd'格式.