如何在Sitecore中配置Lucene以仅索引主数据库上项目的最新版本?

时间:2012-12-04 11:28:08

标签: c# search lucene indexing sitecore

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

我在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>

我像这样查询索引(我在这个答案中使用了techphoria414的SortableIndexSearchContextHow to sort/filter using the new 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的属性,该属性是表示所有其他项目版本的SearchResult的集合。

这是我的问题:

SearchResult代表的项目版本为 NOT 当前发布的商品版本!它似乎是一个随机选择的版本(无论搜索方法在索引中首先命中)。但是,最新版本 包含在SubResults集合中。

E.g:

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

如何防止在主数据库上发生这种情况?要么阻止Lucene索引旧版本的项目,要么通过对结果集进行一些操作来获取SubResults的最新版本?

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

6 个答案:

答案 0 :(得分: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);
    }
}

这可以确保只有最新版本的商品进入您的索引,因此将成为拉出所述索引的唯一商品

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

答案 1 :(得分:8)

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

答案 2 :(得分:7)

如果你让Lucene在你的网络数据库而不是主数据库中进行搜索,它应该只索引最后发布的版本。

<Database>web</Database>

答案 3 :(得分:2)

尽管由他们提供的解决方案,通过使用调整后的排序机制,是一种有趣的方法,但当两个版本的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

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

答案 4 :(得分: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(...));

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

hit

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

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

答案 5 :(得分:0)

我最终从以上答案中找出了另一种解决方案,

从架构上来讲,我认为解决此问题的理想方法是使用更高级别的自定义代码过滤掉较旧版本的结果,而不是将其完全从主数据库索引中删除。您不想管理sitecore旨在解决眼前问题的方式。

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

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

希望这对某人有帮助!