2016-06-21 42 views
1

我想在代码中构建一个搜索谓词,比较Sitecore中的两个字段,并得到一个奇怪的错误消息。基本上,我在每个内容项目上都有两个日期字段 - FirstPublishDate(内容项目首次发布的日期)和LastPublishDate(内容项目发布的最后日期)。我想查找LastPublishDate落在特定日期范围内并且LastPublishDate不等于FirstPublishDate的所有内容项目。使用LINQ这里是我产生判断方法...为什么我无法比较Sitecore 7.5中的搜索谓词中的两个字段?

protected Expression<Func<T, Boolean>> getDateFacetPredicate<T>() where T : MySearchResultItem 
    { 
     var predicate = PredicateBuilder.True<T>(); 

     foreach (var facet in myFacetCategories) 
     { 
      var dateTo = System.DateTime.Now; 
      var dateFrom = dateTo.AddDays(facet.Value*-1); 

      predicate = predicate.And(i => i.LastPublishDate.Between(dateFrom, dateTo, Inclusion.Both)).And(j => j.LastPublishDate != j.FirstPublishDate); 
     } 
     return predicate; 
    } 

然后我用这个谓词在我一般网站的搜索代码来执行搜索如下:上述谓词获取传递给此方法为“ additionalWhere“参数。

public static SearchResults<T> GeneralSearch<T>(string searchText, ISearchIndex index, int currentPage = 0, int pageSize = 20, string language = "", IEnumerable<string> additionalFields = null, 
     Expression<Func<T, Boolean>> additionalWhere = null, Expression<Func<T, Boolean>> additionalFilter = null, IEnumerable<string> facets = null, 
     Expression<Func<T, Boolean>> facetFilter = null, string sortField = null, SortDirection sortDirection = SortDirection.Ascending) where T : SearchResultItem { 

     using (var context = index.CreateSearchContext()) { 
      var query = context.GetQueryable<T>(); 
      if (!string.IsNullOrWhiteSpace(searchText)) { 
       var keywordPred = PredicateBuilder.True<T>(); 

       // take into account escaping of special characters and working around Sitecore limitation with Contains and Equals methods     
       var isSpecialMatch = Regex.IsMatch(searchText, "[" + specialSOLRChars + "]"); 
       if (isSpecialMatch) { 
        var wildcardText = string.Format("\"*{0}*\"", Regex.Replace(searchText, "([" + specialSOLRChars + "])", @"\$1")); 
        wildcardText = wildcardText.Replace(" ", "*"); 
        keywordPred = keywordPred.Or(i => i.Content.MatchWildcard(wildcardText)).Or(i => i.Name.MatchWildcard(wildcardText)); 
       } 
       else { 
        keywordPred = keywordPred.Or(i => i.Content.Contains(searchText)).Or(i => i.Name.Contains(searchText)); 
       } 

       if (additionalFields != null && additionalFields.Any()) { 
        keywordPred = additionalFields.Aggregate(keywordPred, (current, field) => current.Or(i => i[field].Equals(searchText))); 
       } 
       //query = query.Where(i => (i.Content.Contains(searchText) || i.Name.Contains(searchText))); // more explicit call to check the content or item name for our term 
       query = query.Where(keywordPred); 
      } 

      if (language == string.Empty) { 
       language = Sitecore.Context.Language.ToString(); 
      } 

      if (language != null) { 
       query = query.Filter(i => i.Language.Equals(language)); 
      } 

      query = query.Page(currentPage, pageSize); 

      if (additionalWhere != null) { 
       query = query.Where(additionalWhere); 
      } 

      if (additionalFilter != null) { 
       query = query.Filter(additionalFilter); 
      } 

      query = query.ApplySecurityFilter(); 

      FacetResults resultFacets = null; 
      if (facets != null && facets.Any()) { 
       resultFacets = facets.Aggregate(query, (current, fname) => current.FacetOn(i => i[fname])).GetFacets(); 
      } 
      // calling this before applying facetFilter should allow us to get a total facet set 
      // instead of just those related to the current result set 
      // var resultFacets = query.GetFacets();  

      // apply after getting facets for more complete facet list 
      if (facetFilter != null) { 
       query = query.Where(facetFilter); 
      } 

      if (sortField != null) 
      { 
       if (sortDirection == SortDirection.Ascending) 
       { 
        query = query.OrderBy(x => x[sortField]); 
       } 
       else 
       { 
        query = query.OrderByDescending(x => x[sortField]); 
       } 
      } 

      var results = query.GetResults(); // this enumerates the actual results 
      return new SearchResults<T>(results.Hits, results.TotalSearchResults, resultFacets); 
     } 
    } 

当我尝试这个,我得到了以下错误消息:

Server Error in '/' Application. 

No constant node in query node of type:  'Sitecore.ContentSearch.Linq.Nodes.EqualNode'. Left:  'Sitecore.ContentSearch.Linq.Nodes.FieldNode'. Right:  'Sitecore.ContentSearch.Linq.Nodes.FieldNode'. 

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.NotSupportedException: No constant node in query node of type: 'Sitecore.ContentSearch.Linq.Nodes.EqualNode'. Left: 'Sitecore.ContentSearch.Linq.Nodes.FieldNode'. Right: 'Sitecore.ContentSearch.Linq.Nodes.FieldNode'. 

Source Error: 


Line 548:    FacetResults resultFacets = null; 
Line 549:    if (facets != null && facets.Any()) { 
Line 550:     resultFacets = facets.Aggregate(query, (current, fname) => current.FacetOn(i => i[fname])).GetFacets(); 
Line 551:    } 
Line 552:    // calling this before applying facetFilter should allow us to get a total facet set 

从我能理解它似乎不喜欢,我想比较两个不同领域的每一个错误信息其他而不是将一个字段与一个常量进行比较。另一件奇怪的事情是,这个错误似乎是指向与汇总方面有关的一行代码。我做了一次Google搜索,结果完全没有涉及到这个错误。有任何想法吗?

感谢, 科瑞

回答

3

我知道你在想是不可能的,如果你看一下this可能确实如此。给出的解决方案是将您的逻辑放在索引中:创建一个ComputedField,用于检查日期并将值放入可以搜索的索引中(可以是简单的布尔值)。 虽然你需要分割你的逻辑 - 日期范围上的查询仍然可以在谓词中完成(因为它是相对于当前日期),但第一个和最后一个的比较应该在索引时间而不是查询上完成时间。