为什么我不能比较 Sitecore 7.5 中搜索谓词中的两个字段?

Why can't I compare two fields in a search predicate in Sitecore 7.5?

我试图在代码中构建一个搜索谓词来比较 Sitecore 中的两个字段,但我收到了一条奇怪的错误消息。基本上我在每个内容项上都有两个日期字段 - FirstPublishDate(内容项首次发布的日期)和 LastPublishDate(内容项发布的最后日期)。我想找到 LastPublishDate 在特定日期范围内并且 LastPublishDate 不等于 FirstPublishDate 的所有内容项。这里使用 Linq 是我生成谓词的方法...

    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 搜索,但没有找到任何与此错误相关的信息。有什么想法吗?

谢谢, 科里

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