SOLR - 在保持facet结果中的原始值的同时,对facet值进行大小写

时间:2017-12-01 10:12:07

标签: solr

我正在查询一个如下所示的facet字段:

<field name="brand" type="string" indexed="true" stored="false />

string类型定义:

<fieldType name="string" class="solr.StrField" sortMissingLast="true" docValues="true"/>

我根据indexf.brand.facet.sort=index值进行排序。

这给我一个这样的结果:

Aaaa (5)
Bbbb (14
Cccc (8)
abbb (29)

我想对不区分大小写的值进行排序,因此我尝试使用fieldType创建新的LowerCaseFilterFactory

<fieldType name="text_facet" class="solr.TextField">
    <analyzer type="index">
        <tokenizer class="solr.KeywordTokenizerFactory"/>
        <filter class="solr.LowerCaseFilterFactory"/>
    </analyzer>
    <analyzer type="query">
        <tokenizer class="solr.KeywordTokenizerFactory"/>
        <filter class="solr.LowerCaseFilterFactory"/>
    </analyzer>
</fieldType>

重建索引后,结果如下所示:

aaaa (5)
abbb (29)
bbbb (14)
cccc (8)

顺序正确,但现在的值也是LowerCase。

我想要这个结果:

Aaaa (5)
abbb (29)
Bbbb (14)
Cccc (8)

这里的大多数帖子都告诉我要创建一个copyField,但我不明白在面向查询时我如何将这两个字段组合起来。

有没有办法对facet值进行排序不区分大小写,同时在查询时保留原始值?

1 个答案:

答案 0 :(得分:1)

首先,没有直接的做法。我认为使用copyField的建议是别的,但我可能会有所帮助。

我的想法如下:您创建类型为string品牌字段,而不是copyField小写字段。

<field name="brand" type="string" indexed="true" stored="false"/>
<field name="brand_text" type="text_facet" indexed="true" stored="false"/>
<fieldType name="string" class="solr.StrField" sortMissingLast="true" docValues="true"/>

<fieldType name="text_facet" class="solr.TextField">
        <analyzer type="query">
            <tokenizer class="solr.KeywordTokenizerFactory"/>
            <filter class="solr.LowerCaseFilterFactory"/>
        </analyzer>
</fieldType>

<copyField source="brand" dest="brand_text" />

在查询期间,您只需查询两个字段以进行分面处理 - 在您的情况下,它将是这样的(我已经添加了一些文档):

brand:[Aaaa (1), Bbbb (1), Cccc (1), aBbb (1), abbb (1)]
brand_text:[aaaa (1), abbb (2), bbbb (1), cccc (1)]

只要按brand_text排序,就可以获得原始方面的值,并以某种方式提供正确的响应。

但是,我想指出,类似的小写值可能会混合在一起。在我们的例子中,ABbbabbb在小写模式下完全相同,所以问题是,你想在那里展示什么,所以我认为它应该得到妥善处理在业务逻辑方面。

通过扩展负责Solr faceting的org.apache.solr.handler.component.FacetComponent,可以实现完全正确的解决方案。有一个代码正在进行排序:

      boolean countSorted = dff.sort.equals(FacetParams.FACET_SORT_COUNT);
      if (countSorted) {
        counts = dff.countSorted;
        if (counts == null || dff.needRefinements) {
          counts = dff.getCountSorted();
        }
      } else if (dff.sort.equals(FacetParams.FACET_SORT_INDEX)) {
        counts = dff.getLexSorted();
      } else { // TODO: log error or throw exception?
        counts = dff.getLexSorted();
      }

getLexSorted正是对术语进行排序的原因:

Arrays.sort(arr, (o1, o2) -> o1.indexed.compareTo(o2.indexed));

您只需将toLowerCase()应用于o1o2。但是,这种方法将更加困难 - 您需要实现(扩展现有的FacetComponent,然后在solrconfig.xml中启用它,包括CI等)。