Solr:通配符和区分大小写搜索

时间:2017-10-25 18:22:50

标签: search solr lucene

我一直在四处寻找,试图弄清楚这里发生了什么,但到目前为止还是空洞的。我希望有人可以就我在哪里寻找解决方案提供指导。我有一个文本字段定义如下:

<fieldType name="text" class="solr.TextField" positionIncrementGap="100">
  <analyzer type="index">
    <tokenizer class="solr.WhitespaceTokenizerFactory"/>
    <!-- in this example, we will only use synonyms at query time
    <filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
    -->
    <filter class="solr.StopFilterFactory"
            ignoreCase="true"
            words="stopwords.txt"
            />
    <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="0"/>
    <filter class="solr.LowerCaseFilterFactory"/>
    <filter class="solr.SnowballPorterFilterFactory" language="English" protected="protwords.txt"/>
    <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
  </analyzer>
  <analyzer type="query">
    <tokenizer class="solr.WhitespaceTokenizerFactory"/>
    <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
    <filter class="solr.StopFilterFactory"
            ignoreCase="true"
            words="stopwords.txt"
            />
    <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="0"/>
    <filter class="solr.LowerCaseFilterFactory"/>
    <filter class="solr.SnowballPorterFilterFactory" language="English" protected="protwords.txt"/>
    <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
  </analyzer>
</fieldType>

我有一些记录具有以下键/值

"text":[
  "NOFX_SiteTest_4",
  "NOFX_SiteTest_4\nNOFX_SiteTest_4\n Fourteen\n Ten\n Thirteen\n Fifteen\n Two\n 3\n Select Fields"
]


"text":[
  "NOFX_SiteTest_44",
  "NOFX_SiteTest_44\nNOFX_SiteTest_44\n Fourteen\n Ten\n Thirteen\n Fifteen\n Two\n 3\n Select Fields"
]


"text":[
  "NOFX_SiteTest_445",
  "NOFX_SiteTest_445\nNOFX_SiteTest_445\n Fourteen\n Ten\n Thirteen\n Fifteen\n Two\n 3\n Select Fields"
]

我尝试各种搜索让Solr返回这些记录。问题是,取决于我如何构造查询(基于我添加通配符的位置,如果我添加通配符,以及关于下划线的搜索文本),我得到的结果是意外和不正确的。以下是我从Solr Admin查询页面运行的搜索:

SEARCH
text:(( NOFX_SiteTest_4* )) OR text_exact:(( NOFX_SiteTest_4* ))

RESULT
3 Records (correct)

SEARCH
text:(( NOFX_SiteTest_ )) OR text_exact:(( NOFX_SiteTest_ ))

RESULT
3 Records (correct)

SEARCH
text:(( NOFX_SiteTest )) OR text_exact:(( NOFX_SiteTest ))

RESULT
3 Records (correct)

SEARCH
text:(( NOFX_SiteTest* )) OR text_exact:(( NOFX_SiteTest* ))

RESULT
3 Records (correct)

SEARCH
text:(( nofx_sitetest_4 )) OR text_exact:(( nofx_sitetest_4 ))

RESULT
1 Record (correct)

SEARCH
text:(( nofx_sitetest_4* )) OR text_exact:(( nofx_sitetest_4* ))

RESULT
0 Records (incorrect)

SEARCH
text:(( nofx_sitetest_ )) OR text_exact:(( nofx_sitetest_ ))

RESULT
3 Records (correct)

SEARCH
text:(( nofx_sitetest* )) OR text_exact:(( nofx_sitetest* ))

RESULT
0 Records (incorrect)

从我看来,根据这个字段的配置,Solr应该看到这两个查询是相同的:

text:(( NOFX_SiteTest_4* )) OR text_exact:(( NOFX_SiteTest_4* ))

text:(( nofx_sitetest_4* )) OR text_exact:(( nofx_sitetest_4* ))

为什么第一次搜索,字母大写合适,返回适当数量的记录,但第二次搜索,所有小写,但不是。但是,在运行这些查询时:

text:(( NOFX_SiteTest_ )) OR text_exact:(( NOFX_SiteTest_ ))

text:(( nofx_sitetest_ )) OR text_exact:(( nofx_sitetest_ ))

返回正确数量的记录。为什么包含通配符会导致问题?特别是当搜索完全由小写字母组成时?

我希望有人能指出我正确的方向。我一直在查看文档并搜索类似的问题,但我遇到的任何事情似乎都无助于解决我的问题或帮助我理解为什么会出现这种问题。

编辑:一些其他信息。

以下是我在上面的搜索中使用的两个字段的定义:

<field name="text"       type="text"       indexed="true"  stored="true"  multiValued="true"/>
<field name="text_exact" type="text_exact" indexed="false"  stored="false" multiValued="true"/>

<!-- copy all fields to the default search field -->
<copyField source="title"   dest="text"/>
<copyField source="content" dest="text"/>
<copyField source="Comment" dest="text"/>

<!-- copy all fields to the exact match search field -->
<copyField source="title"   dest="text_exact"/>
<copyField source="content" dest="text_exact"/>
<copyField source="Comment" dest="text_exact"/>

texttext_exact之间的唯一区别是如何定义字段类型。我的搜索是

text:(( NOFX_SiteTest_4* )) OR text_exact:(( NOFX_SiteTest_4* ))

它会找到3条记录(如上所述),但由于text_exact字段而不是text字段,它会这样做。我发现这很奇怪。运行搜索

text_exact:(( NOFX_SiteTest_4* ))

返回3条记录,但正在运行搜索

text:(( NOFX_SiteTest_4* ))

返回0条记录。我可以看到text_exact返回数据的原因。因为text_exact字段中有确切的文字。但我不确定为什么对text的搜索不会产生任何记录。那个领域不应该更开放和宽容吗?并且更加允许通配符搜索?因为如果我删除星号,它会返回一个记录,其中该确切文本位于text字段中。为什么不把星号称为通配符?

最后,如果我删除通配符并将文本更改为全部小写,则在搜索text字段时,它会毫无困难地找到该记录。所以,无论问题是什么,它似乎都与使用星号作为通配符有关。

2 个答案:

答案 0 :(得分:0)

首先是LowerCaseFilterFactory过滤器,应该在 WordDelimiterFilterFactory 过滤器

之前
<filter class="solr.LowerCaseFilterFactory"/>

它会将所有字符转换为小写,然后它将被wordDelimiterFilter分割

当您使用通配符时,请添加额外的text:(( NOFX_SiteTest_4 )),这将是精确的数学运算。

最终

text:( NOFX_SiteTest_4* ) OR text_exact:( NOFX_SiteTest_4*) OR text:( NOFX_SiteTest_4 )

请使用分析solr工具查看发生的情况。

答案 1 :(得分:0)

当您使用通配符时,分析链并不像通常那样运行。

唯一过滤器invoked are those that implement MultiTermAwareComponent,因此分析页面无法告诉您在那里发生了什么。

这意味着当您进行通配符搜索时,如果索引管道已更改标记(拆分它们等),则该处理将查询时发生。这可能就是为什么你没有按照自己喜欢的方式获得点击量,但没有通配符就可以了。这里的原因是WordDelimiterFilter不是多重软件,所以当你进行索引时,输入文本会被分成多个标记,而当你进行查询时,这并不会发生。由于令牌不匹配(我猜测只有NOFX *可能会匹配,因为这将是双方的单个令牌),你不会受到打击。

如果你要求分析文本的通配符匹配,你可能不得不改为使用NgramFilter,然后调整该过滤器以获得每个令牌所需的结果。但是,这将再次表现不同,具体取决于您在链中添加NgramFilter的位置(即在字分隔符之前或之后等)。