【问题标题】:Sitecore ContentSearch index descendantsSitecore ContentSearch 索引后代
【发布时间】:2014-11-12 09:47:26
【问题描述】:

我在编写查询以选择项目的后代具有某些属性的项目时遇到了一些问题。我正在使用 Sitecore 7

我想选择带有平面图标的项目,其中任何绿色复选项目的属性 X 和值为 Y。

我需要做一些特别的事情来索引孩子吗? 我的查询尝试是:

var master = Sitecore.ContentSearch.ContentSearchManager.GetIndex("sitecore_master_index");
using (var context = master.CreateSearchContext())
{
    var results = context.GetQueryable<SearchResultItem>()
                        .Where(x => x.TemplateId == productTemplateId
                            && x.GetDescendants<SearchResultItem>(context).Any(y => y["X"] == "Y"))
                        .GetResults();

    var hits = results.Hits.ToArray();
}

这会引发以下异常:

System.NotSupportedException: The method 'GetDescendants' is not supported. Declaring type: Sitecore.ContentSearch.SearchTypes.SearchResultItem
Result StackTrace:  
at Sitecore.ContentSearch.Linq.Parsing.ExpressionParser.VisitItemMethod(MethodCallExpression methodCall)
   at Sitecore.ContentSearch.Linq.Parsing.ExpressionParser.VisitMethodCall(MethodCallExpression methodCall)
   at Sitecore.ContentSearch.Linq.Parsing.ExpressionParser.Visit(Expression expression)
   at Sitecore.ContentSearch.Linq.Parsing.ExpressionParser.VisitAnyMethod(MethodCallExpression methodCall)
   at Sitecore.ContentSearch.Linq.Parsing.ExpressionParser.VisitQueryableMethod(MethodCallExpression methodCall)
   at Sitecore.ContentSearch.Linq.Parsing.ExpressionParser.VisitMethodCall(MethodCallExpression methodCall)
   at Sitecore.ContentSearch.Linq.Parsing.ExpressionParser.Visit(Expression expression)
   at Sitecore.ContentSearch.Linq.Parsing.ExpressionParser.VisitBinary(BinaryExpression expression)
   at Sitecore.ContentSearch.Linq.Parsing.ExpressionParser.Visit(Expression expression)
   at Sitecore.ContentSearch.Linq.Parsing.ExpressionParser.VisitWhereMethod(MethodCallExpression methodCall)
   at Sitecore.ContentSearch.Linq.Parsing.ExpressionParser.VisitQueryableMethod(MethodCallExpression methodCall)
   at Sitecore.ContentSearch.Linq.Parsing.ExpressionParser.VisitMethodCall(MethodCallExpression methodCall)
   at Sitecore.ContentSearch.Linq.Parsing.ExpressionParser.Visit(Expression expression)
   at Sitecore.ContentSearch.Linq.Parsing.ExpressionParser.VisitGetResultsMethod(MethodCallExpression methodCall)
   at Sitecore.ContentSearch.Linq.Parsing.ExpressionParser.VisitQueryableExtensionMethod(MethodCallExpression methodCall)
   at Sitecore.ContentSearch.Linq.Parsing.ExpressionParser.VisitMethodCall(MethodCallExpression methodCall)
   at Sitecore.ContentSearch.Linq.Parsing.ExpressionParser.Visit(Expression expression)
   at Sitecore.ContentSearch.Linq.Parsing.ExpressionParser.Parse(Expression expression)
   at Sitecore.ContentSearch.Linq.Parsing.GenericQueryable`2.GetQuery(Expression expression)
   at Sitecore.ContentSearch.Linq.Parsing.GenericQueryable`2.Execute[TResult](Expression expression)
   at Sitecore.ContentSearch.Linq.QueryableExtensions.GetResults[TSource](IQueryable`1 source)

我不知道为什么。

【问题讨论】:

    标签: lucene sitecore sitecore7


    【解决方案1】:

    您不能使用GetDescendants,因为它尚未在 ContentSearch 表达式解析器中实现。
    在 Sitecore 搜索中,您需要按项目路径查找后代。
    所以先获取匹配模板productTemplateId的item,再获取item path以第一个result路径开头的item。

    我确信有一种方法可以在一个表达式中执行此操作(可能使用 Join),但我不知道如何。

    【讨论】:

      【解决方案2】:

      Sitecore 内容搜索 API 不支持使用“GetDescendants”方法,但是您可以使用以下代码作为解决方法,

      请注意,我在您的绿色检查模板而不是 productTemplateId 上进行过滤:

      var master = Sitecore.ContentSearch.ContentSearchManager.GetIndex("sitecore_master_index");
              using (var context = master.CreateSearchContext())
              {
                  var Products = new List<Item>();
                  var results = context.GetQueryable<SearchResultItem>()
                                      .Where(x => x.TemplateId == GreenCheckTemplateID
                                          && x["X"] == "Y")
                                      .GetResults();
      
                  foreach (SearchHit<SitecoreItem> result in results.Hits)
                  { 
                       var product = result.Document.GetItem().Parent.Parent;
                       if(!Products.Where(i=>i.ID.Equals(product.ID).Any())
                       {
                          Products.Add(product);
                        }
                  }
              }
      

      【讨论】:

        【解决方案3】:

        前面的答案是正确的,因为 Linq to ContentSearch 不包含 GetDescendants() 的定义。

        克服此限制的另一个选择是创建您自己的 IQueriable 扩展,类似于此处描述的内容:http://thegrumpycoder.com/post/75297631359/extending-sitecore-contentsearch-with-iqueryable。您可以创建 FilterDescendants(fieldName, value) 扩展,它接受字段名称和过滤后代的值。

        所以你的陈述是

            var results = context.GetQueryable<SearchResultItem>()
                                            .Where(x => x.TemplateId == productTemplateId)
                                            .FilterDescendants(fieldName, value)
                                            .GetResults();
        

        又好又干净!

        【讨论】:

          【解决方案4】:

          您还可以创建自定义计算字段,存储选中项的值并在自定义字段上查询。

          详细解释可以看这里:
          http://www.sitecore.net/nl-nl/learn/blogs/technical-blogs/john-west-sitecore-blog/posts/2013/03/sitecore-7-computed-index-fields.aspx

          编辑:使用这种方法,您还必须在保存一个选中的项目时触发 parent.parent 项目的索引更新(您可以使用事件并调用 IndexCustodian.UpdateItem 来做到这一点)。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-07-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多