【问题标题】:Sitecore search: Get results term by termSitecore 搜索:逐项获取结果
【发布时间】:2015-07-28 09:58:06
【问题描述】:

在这里,我正在尝试获取多个字词的搜索结果。说 fulltext="Lee jeans",然后 regexresult={"lee","jeans"}。

代码:

IProviderSearchContext searchContext = index.CreateSearchContext();
IQueryable<SearchItem> scQuery = searchContext.GetQueryable<SearchItem>();
var predicate = PredicateBuilder.True<SearchItem>();

   //checking if the fulltext includes terms within " "
                    var regexResult = SearchRegexHelper.getSearchRegexResult(fulltext);

                    regexResult.Remove(" ");

                    foreach (string term in regexResult)
                    {
                        predicate = predicate.Or(p => p.TextContent.Contains(term));
                    }
                    scQuery = scQuery.Where(predicate);

IEnumerable<SearchHit<SearchItem>> results = scQuery.GetResults().Hits;

results=sortResult(results);

排序基于站点核心字段:

  switch (query.Sort)
  {
    case SearchQuerySort.Date:
    results = results.OrderBy(x => GetValue(x.Document, FieldNames.StartDate));
    break;
    case SearchQuerySort.Alphabetically:
    results = results.OrderBy(x => GetValue(x.Document, FieldNames.Profile));
    break;
    case SearchQuerySort.Default:
    default:
    results = results.OrderByDescending(x => GetValue(x.Document, FieldNames.Updated));
    break;
}

现在,我需要先获得“lee”的结果并对它们进行排序,然后找到“jeans”的结果并对其进行排序。最终的搜索结果将首先包含“lee”和“jeans”的连接排序项集。

因此,我们必须先获得“lee”的结果,然后才能获得“jeans”的结果

有没有办法逐项获得结果?

【问题讨论】:

  • 我不太了解用例。你说你想先点击“lee”然后点击“jeans”。但是,如果您按字母顺序排序,那么整个结果集应该按字母顺序排序,不是吗?您能否提供一些具有预期输出的示例输入?
  • @Christian 当前的代码情况正在按照你说的做。但这不是我需要的。考虑默认排序,即。最新更新的项目。预期的情况。如果 regexResult 有 {"Jack","Daniels"} 那么我们应该:首先,获取 "Jack" 的最新更新项目。其次,获取“丹尼尔斯”的最新更新项目。因此,结果将是 First,然后是 Second。
  • 我不同意你的逻辑。如果您在 Google 中键入“Jack Daniels”,那么您会期望它匹配与 Jack AND Daniels 最相关的所有内容,按其他任何内容排序应该忽略其他所有内容并仅按该标准排序。但无论如何,我已经用可能的解决方案更新了我的答案......
  • @Jammy 我完全同意你的看法。所以我们可以将“Jack Daniels”添加为第一个词(最相关),让其他人继续。

标签: linq search sitecore iqueryable predicatebuilder


【解决方案1】:

您可以使用 Query-Time Boosting 使术语更具相关性,从而影响排名:

你想给第一个词最高的提升,然后逐渐减少每个额外的词:

var regexResult = SearchRegexHelper.getSearchRegexResult(fulltext);
regexResult.Remove(" ");
float boost = regexResult.Count();

foreach (string term in regexResult)
{
    predicate = predicate.Or(p => p.TextContent.Contains(term)).Boost(boost--);
}

编辑: 在同一个查询中进行提升和排序是不可能的,至少,排序将撤消由于提升而返回的基于“相关性”的排序。

另一种方法是多次搜索并连接返回单个列表的结果。效率不高,因为您实际上是在进行多次搜索:

IProviderSearchContext searchContext = index.CreateSearchContext();
var items = new List<SearchResultItem>();

var regexResult = SearchRegexHelper.getSearchRegexResult(fulltext);

regexResult.Remove(" ");

foreach (string term in regexResult)
{
    var results = searchContext.GetQueryable<SearchResultItem>()
                                   .Where(p => p.Content.Contains(term));
    SortSearchResults(results); //results passed in by reference, no need to return object to set it back to itself

    items.AddRange(results);
}

注意:以上没有考虑结果集之间的重复。

【讨论】:

  • 我主要关心的是获取“lee”的所有结果,并在获取“jeans”的结果之前对其进行排序。
  • @Prathameshdhanawade 你用什么来排序你的结果?请张贴排序方法的代码。
  • “在同一个查询中提升和排序是不可能的”,实际上如果你使用 solr 是可能的(不确定 lucene)。您可以编写如下排序查询:dataQuery.OrderByDescending(i => i["score"]).ThenByDescending(i => i.Title);
  • @EhabElGindy 很高兴知道这很有意义。我想增加你的提升因子以使结果更加倾斜是明智的,这样交叉的机会就会减少。
  • 我肯定会回避多个查询 + concat 结果方法,因为这会开始给您带来性能问题。提升是一个不错的方法。另请注意,当您使用 OR 谓词进行搜索时,具有多个匹配项的结果在 SOLR 中的得分已经更高。 SOLR 会给带有“Lee”和“Jeans”的东西比只有“Lee”或“Jeans”的东西更高的分数。
猜你喜欢
  • 2016-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-17
  • 2012-04-10
  • 2013-01-30
相关资源
最近更新 更多