如何在迁移到新版本的Lucene时转换使用RangeQuery的BooleanQuery?

时间:2015-01-30 15:05:54

标签: c# .net sitecore lucene.net

我有一个我继承的应用程序(使用Sitecore CMS)。我们刚刚升级了Sitecore,要求我们使用更新版本的Lucene.Net。我们的一些旧代码破了。问题是,我无法弄清楚代码试图做什么。我根本不熟悉Lucene的查询。特别是,我知道我们的RangeQueries现在必须是TermRangeQueries,但是在重写这段代码时我很困难,因为我找不到BooleanQuery的替代方案而且它赢了接受TermRangeQuery作为输入。

     BooleanQuery lQuery = new BooleanQuery();
     lQuery.Add(new TermQuery(new Term("_shorttemplateid", string.Format("{0}", ShortID.Encode(templateId).ToLowerInvariant()))),
                Lucene.Net.Search.Occur.MUST);
     if (string.IsNullOrEmpty(endDateItemFieldName))
     {
         lQuery.Add(
            new RangeQuery(
               new Term(startDateItemFieldName, startDateTime),
               new Term(startDateItemFieldName, endDateTime), true),
               Lucene.Net.Search.Occur.MUST);
     }
     else
     {
         lQuery.Add(
            new RangeQuery(
               new Term(startDateItemFieldName, startDate.ToString(DATE_TIME_FORMAT)),
               new Term(startDateItemFieldName, string.Format("{0}{1}", endDate.ToString("yyyyMMdd"), endTimeStamp)), true),
               Lucene.Net.Search.Occur.SHOULD);
         lQuery.Add(
            new RangeQuery(
               new Term(endDateItemFieldName, startDate.ToString(DATE_TIME_FORMAT)),
               new Term(endDateItemFieldName, string.Format("{0}{1}", endDate.ToString("yyyyMMdd"), endTimeStamp)), true),
               Lucene.Net.Search.Occur.MUST);
     }

2 个答案:

答案 0 :(得分:1)

您的示例中的代码使用以下逻辑构建Lucene查询:

<强>的伪代码:

Match all documents 

     That have a specific template ID

     AND

         IF an endDateItemFieldName is present

             The start date must be between date X and Y

         ELSE

             The start date can be between date X and Y
             But the end date must be between date X and Y

在幕后,这会产生类似于此的Lucene查询:

+_shorttemplateid:3f2504e04f8941d39a0c0305e82c3301 start:[20020101 TO 20030101] +end:[20020101 TO 20030101]

在Sitecore 7+中,很多&#34; Luceneness&#34;已被抽象出来并由LINQ搜索提供程序为您生成。这允许您在搜索实现(例如,Solr)之间切换,而无需对代码进行任何实质性重构。因为LINQ是如此广为人知,所以与LINQ提供程序一起工作通常更容易让开发人员掌握。

以下是使用新LINQ提供程序的等效搜索查询。

using Sitecore.ContentSearch;
using Sitecore.ContentSearch.Converters;
using Sitecore.ContentSearch.SearchTypes;
using System;
using System.ComponentModel;

namespace YourNamespace
{
    public class DateSearchResultItem : SearchResultItem
    {
        [IndexField("startdate"), TypeConverter(typeof(IndexFieldDateTimeValueConverter))]
        public DateTime StartDate { get; set; }

        [IndexField("enddate"), TypeConverter(typeof(IndexFieldDateTimeValueConverter))]
        public DateTime EndDate { get; set; }
    }
}

一个示例用法:

ISearchIndex index = ContentSearchManager.GetIndex("sitecore_web_index");
using (var context = index.CreateSearchContext())
{
    var results = context.GetQueryable<DateSearchResultItem>()
        .Where(item => item.TemplateId == new ID(templateId));

    if (String.IsNullOrEmpty(endDateItemFieldName))
    {
        results = results
            .Where(item => item.StartDate >= startDateTime)
            .Where(item => item.StartDate <= endDateTime);
    }
    else
    {
        results = results
            .Where(item => item.EndDate >= startDateTime)
            .Where(item => item.EndDate <= endDateTime);
    }

    var compiledQuery = results.GetResults();
    int totalMatches =  compiledQuery.TotalSearchResults;

    foreach (var hit in compiledQuery.Hits)
    {
        Item item = hit.Document.GetItem();
    }
}

答案 1 :(得分:0)

首先,花点时间阅读Sitecore 7+的新Search API的工作原理:

http://www.sitecore.net/Learn/Blogs/Technical-Blogs/Sitecore-7-Development-Team/Posts/2013/06/Sitecore-7-POCO-Explained.aspx

https://www.sitecore.net/Learn/Blogs/Technical-Blogs/Sitecore-7-Development-Team/Posts/2013/04/Sitecore-7-Patterns-for-Global-Search-Context-Reuse.aspx

其次,要在示例中重写代码,请创建以下内容:

public class CustomSearchResult : Sitecore.ContentSearch.SearchTypes.SearchResultItem
{
    [IndexField("START DATE FIELD NAME")]
    public virtual DateTime EndDate {get; set;}

    [IndexField("END DATE FIELD NAME")]
    public virtual DateTime StartDate {get; set;}
} 

现在,您可以执行以下搜索:

using Sitecore.ContentSearch;
using Sitecore.ContentSearch.Linq;
using Sitecore.ContentSearch.SearchTypes;
using Sitecore.ContentSearch.Linq.Utilities

using (var context = ContentSearchManager.GetIndex("sitecore_web_index").CreateSearchContext())
            {
                var results = context.GetQueryable<CustomSearchResult>().Where(i => i.TemplateId == Sitecore.Data.ID.Parse("TEMPLATE GUID") && i.StartDate > StartDateObject && i.EndDate < EndDateObject).GetResults().Hits.Select(i => i.Document.GetItem()).ToList();
                return results;
            }

请注意 StartDateObject EndDateObject 应为DateTime类型。

希望这有帮助。