6

我认识到这是网络数据库上的一个有争议的问题,所以这个问题适用于主数据库......

我在 Sitecore 6.4.1 中设置了一个自定义索引,如下所示:

<index id="search_content_US" type="Sitecore.Search.Index, Sitecore.Kernel">
    <param desc="name">$(id)</param>
    <param desc="folder">_search_content_US</param>
    <Analyzer ref="search/analyzer" />
    <locations hint="list:AddCrawler">
        <search_content_home type="Sitecore.Search.Crawlers.DatabaseCrawler, Sitecore.Kernel">
            <Database>master</Database>
            <Root>/sitecore/content/usa home</Root>
            <Tags>home content</Tags>
        </search_content_home>
    </locations>
</index>

我像这样查询索引(我正在使用SortableIndexSearchContext来自此答案的 techphoria414:如何使用新的 Sitecore.Search API 进行排序/过滤):

private SearchHits GetSearchResults(SortableIndexSearchContext searchContext, string searchTerm)
    {
        CombinedQuery query = new CombinedQuery();
        query.Add(new FullTextQuery(searchTerm), QueryOccurance.Must);
        return searchContext.Search(query, Sort.RELEVANCE);
    }

...

SearchHits hits = GetSearchResults(searchContext, searchTerm);

hits是我的索引中的搜索命中集合。当我遍历时,hits我可以看到 Sitecore 中有许多相同项目的重复项,每个版本的项目 1 个。

然后我执行以下操作以获得SearchResultCollection

SearchResultCollection results = hits.FetchResults(0, hits.Length);

这会将所有重复项组合成一个SearchResult对象。此对象表示特定项目的 1 个版本,并有一个名为的属性,它是代表所有其他项目版本SubResults的 s 的集合。SearchResult

这是我的问题:

所代表的项目版本SearchResult不是该项目的当前发布版本!它似乎是一个随机选择的版本(无论哪种搜索方法在索引中首先出现)。但是,最新版本包含SubResults集合中。

例如:

SearchResult
 |
 |- Version 8 // main result
 ...
 |- SubResults
      |
      |- Version 9 // latest version
      |- Version 3
      |- Version 5
      ... // all versions in random order

如何防止这种情况在主数据库上发生?通过阻止 Lucene 索引项目的旧版本,或者通过对结果集进行一些操作以从SubResults?

顺便说一句,为什么 Lucene 还要费心索引旧版本的项目呢?当然这对于在您的网站上搜索内容毫无意义,因为旧版本不可见?

4

6 回答 6

10

您可以实现覆盖以下内容的自定义爬虫:

public class IndexCrawler : DatabaseCrawler
{
    protected override void IndexVersion(Item item, Item latestVersion, Sitecore.Search.IndexUpdateContext context)
    {
        if (item.Versions.Count > 0 && item.Version.Number != latestVersion.Version.Number)
            return;

        base.IndexVersion(item, latestVersion, context);
    }
}

这确保只有最新版本的项目进入您的索引,因此将是唯一从所述索引中拉出的项目

您当然需要更新配置文件以设置正确的索引类型

于 2013-02-06T17:11:54.917 回答
8

Sitecore 7中,索引中添加了一个字段_latestversion,其中包含最新版本的“1”(其他版本为空值)。

于 2013-08-19T13:06:35.870 回答
7

如果您让 Lucene 在您的 Web 数据库中搜索而不是在 Master 中搜索,它应该只索引最后发布的版本。

<Database>web</Database>
于 2012-12-04T11:51:07.793 回答
2

虽然yetiman 提供的解决方案通过使用调整后的排序机制是一种有趣的方法,但当两个版本的Lucene 结果分数趋于不同时,它并不能提供完美的解决方案。例如,在分数为 0.7 的 v1 和分数为 0.5 的 v2 中,他的解决方案仍将返回项目的第一个版本。(至少在我的测试中。)

经过更多挖掘,最明显的解决方案显然在于实现您自己的Sitecore.Pipelines.Search.SearchSystemIndex并使用该解决方案而不是默认解决方案。如果您使用 ILSpy 或类似工具反编译该代码,您会在方法底部注意到以下内容Process

foreach (SearchResult current in searchHits.FetchResults(0, searchHits.Length)){
  // ...
}

每个这样SearchResult的实际上都是分组的,其中从 Lucene 返回的第一个结果(因此得分最高的结果)是主要结果。Subresults通过每个实例的属性可以访问同一项目的其他版本(以及其他语言)的命中;或者null没有的时候。

根据您的要求,您可以调整课程的这一部分以满足您的需要。

于 2013-01-04T07:46:55.067 回答
0

虽然我还没有想出确切的答案(停止 Lucene 在主数据库上索引旧版本),但我想出了一个可以接受的解决方法......

当 Lucene 从索引返回它的结果时,每个hit都有一个名为的字段"_id",其格式如下(同一项目的 3 个版本,其中最后一个数字是版本):

"CCB75380-4E9A-4921-99EC-65E532E330FF%en%1"
"CCB75380-4E9A-4921-99EC-65E532E330FF%en%2"
"CCB75380-4E9A-4921-99EC-65E532E330FF%en%3"
...

我目前正在按Sort.RELEVANCE默认排序。如果我们在索引中只有一个项目的版本,这很好,但有几个几乎相同的版本,它们都具有相同的相关性分数,而 Lucene 只是以任何顺序将它们搅出。Sitecore 然后获取项目版本的第一个实例(即使它是旧的)。

解决方案是指定辅助排序字段。在该searchContext.Search()方法中,您可以传递一个自定义Sort对象。

searchContext.Search(query, new Sort(...));

通过首先按 Lucene 的内置排序Sort.RELEVANCE然后id索引中的字段(降序)排序,我可以确保hitSitecore 看到的第一个将是最新版本,而不仅仅是随机版本:

searchContext.Search(query, new Sort
                            (
                                new SortField[2] 
                                {
                                    SortField.FIELD_SCORE, // equivalent to Sort.RELEVANCE
                                    new SortField("_id",SortField.STRING, true) // sort by _id, descending
                                }
                            )
);

SortField参数如下:

SortField(string fieldName, int type, bool reverse)

这种方法解决了我的问题,但如果有人真的能找到如何只索引最新版本,请回答!

于 2012-12-05T15:03:18.297 回答
0

我最终从上述答案中找到了一个替代解决方案,

从架构上讲,我认为这个问题的理想解决方案是使用更高级别的自定义代码过滤掉旧版本的结果,而不是完全从主数据库索引中删除它们。您不想管理 sitecore 旨在解决手头问题的方式。

使用以下谓词过滤掉旧版本并仅检索最新版本

predicate.And(item=>item[Sitecore.ContentSearch.BuiltinFields.LatestVersion].Equals("1"));

希望这可以帮助某人!

于 2019-08-23T18:58:27.333 回答