Запрос Lucne-индекса Sitecore с помощью ContentSearch-API по диапазону DateTime

В данный момент я работаю над проектом по внедрению Sitecore 7.0 Update 2

В моем шаблоне данных у меня есть это поле с именем "Дата начала" и еще одно "Дата окончания". Эти два поля создаются с типом "Дата" (не Datetime). Так что он показывает средство выбора даты, когда я редактирую и создаю элементы, и я подал некоторые элементы с фиктивным контентом и датами начала и окончания с прошлого месяца и текущего месяца.

Чего я хочу добиться, так это получить все предметы за выбранный месяц. Мой метод содержит в качестве параметра целое число месяца и года. Это должно контролировать элементы с начальной и конечной датами, которые должны быть получены из Lucene sitecore_master_index. Необработанные значения Sitecore для поля Date представляют собой строки datetime ISO.

Так что это запрос, где я пытаюсь получить все элементы из этого выбранного месяца.

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 я рассчитываю вернуть все элементы шаблона Events, которые должны содержать дату в этом месяце. Но он возвращает пустой набор результатов. Недостатком является то, что я не могу отладить Lamba-выражение, поэтому, к сожалению, я не знаю значения в этой области. Но не что-то между годом 1 и 9999:) После того, как IQueryable выполнил запрос и что-то возвратил, объекты в списке содержат правильный DateTime для свойств. Таким образом, он сопоставляет поля из индекса правильно со свойствами. Также, если я удаляю проверку даты, так что только проверка TemplateID является предложением Where, она возвращает результаты. Но даже сравнение Begin Date с 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 (Java-приложении для просмотра содержимого Lucene-индекса) после переиндексации появляется поле и содержит заданную дату для этого элемента (в 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();

Это было решением в другом вопросе здесь о переполнении стека. Но я не считаю это лучшей практикой и надежным. У Google, к сожалению, не было никаких других альтернатив. Я думаю, что-то, как я представляю, это будет возможно, верно?

У кого-нибудь есть опыт фильтрации Lucene-результатов по DateTime от IQueryable? И может указать мне в правильном направлении?

2 ответа

Решение

Попробуйте следующее:

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", например, 18 февраля 2014 года индексируется как 20140218, так что вы можете видеть его сохраняются как целое число, а год, месяц и день находятся в одном поле, поэтому вы не можете сравнивать только год или месяц и т. д.

Теперь в Sitecore linq, если вы хотите выполнить запрос к полю даты, вы ДОЛЖНЫ сравнить его с типом "DateTime", Sitecore знает, что объект DateTime должен быть преобразован в формат "yyyyMMdd" перед передачей его в Lucene.

Вы можете попытаться удалить подчеркивания из определения поля в конфигурации индекса и в элементе 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; }
Другие вопросы по тегам