Java Solr通配符搜索结果不正确

Java Solr通配符搜索结果不正确,java,solr,tokenize,Java,Solr,Tokenize,在进行通配符查询时,出现了一些意外的结果。我正在使用Solr6.6.0。solr ui中的eDiscoveryMax处理程序。以下查询按预期返回不带通配符的结果-firstNames:James,但添加通配符时未找到任何结果。 对于firstNames字段,我使用默认的fieldType text_en和默认的标记器和过滤器。当我对firstNames:Stephen和firstNames:Stephen*运行完全相同的查询时,我得到了通配符搜索和非通配符搜索的结果。下面是schema.xml中

在进行通配符查询时,出现了一些意外的结果。我正在使用Solr6.6.0。solr ui中的eDiscoveryMax处理程序。以下查询按预期返回不带通配符的结果-firstNames:James,但添加通配符时未找到任何结果。 对于firstNames字段,我使用默认的fieldType text_en和默认的标记器和过滤器。当我对firstNames:Stephen和firstNames:Stephen*运行完全相同的查询时,我得到了通配符搜索和非通配符搜索的结果。下面是schema.xml中的字段xml:

  <field name="firstNames" type="text_en" multiValued="true" indexed="true" stored="true"/>


  • 不要删除停止词。这是20世纪70年代的一次节省空间的黑客攻击。它使一些单词无法搜索,所以像“vitamin a”这样的查询永远不会起作用,因为“a”是一个停止词。下面是一篇博客文章,列出了100%是停止语的电影标题
  • 不要使用带有词干的通配符。这将在词干上显示匹配项,而不是表面单词。您需要一个仅包含小写筛选器的单独字段

  • 不要在人名上使用词干。例如,您不想将“史蒂夫·乔布斯”改为“史蒂夫·乔布斯”,或将“威廉·戈尔丁”改为“威廉·戈尔德”

  • 更好的是,使用ICU折叠式过滤器,而不仅仅是小写


  • 当您执行通配符查询时,不会调用分析链(这是一个小谎言——确实如此,但仅限于MultiTermAware组件——这通常意味着LowercaseFilter是唯一仍然处于活动状态的组件)

    由于您有一个词干过滤器和所有格过滤器,因此
    James
    上的end
    s
    将被删除。由于这只发生在索引时间(请记住,当您使用通配符时,通常会在查询时跳过分析链),因此标记
    jame
    存储在索引中

    当您进行查询时,
    firstNames:James*
    ,您要求Solr“查找包含以
    James
    开头的令牌的任何文档。由于存储的是令牌
    jame
    ,因此没有与
    James
    匹配的令牌

    当您使用
    Stephen
    尝试此操作时,词干筛选或所有格筛选都不会删除单词的结尾,因此
    Stephen*
    会查找任何以
    Stephen
    开头的标记,并且由于该标记存在(没有更改),因此会返回匹配项


    解决方案取决于您的用例;不需要在名称字段上使用词干或所有格过滤器,因为这对名称没有实际意义(相反,您可以应用自己的逻辑来匹配相似的名称)。另一种选择是使用ngramfilter,有效地为令牌的每个前缀和中缀版本生成令牌(
    foo
    f
    fo
    oo
    o
    )。

    关于停止字,对“我是否必须使用停止字”问题的回答不是“是”或“否”。答案是“为什么不”“但要明智地根据你的数据。 对于药物数据库,“a”、“b”、“c”。。。不应在stopwords定义文件中。
    对于100%停止词数据库的电影标题,标题字段不能使用停止词,但描述字段可能应该使用。

    为名字创建2-3个复制字段并进行不同分析是否是一种好方法,这样我就可以匹配准确的搜索词并保留通配符,并猜测通配符匹配的得分会更低。是的,这是一种常见的方法。一个字段用于精确匹配,一个字段用于语音匹配,其他字段用于满足应用程序中的任何要求。需求应该引导必要的领域,而不仅仅是哪些领域可能有用。
      <fieldType name="text_en" class="solr.TextField" positionIncrementGap="100">
        <analyzer type="index">
          <tokenizer class="solr.StandardTokenizerFactory"/>
          <filter class="solr.StopFilterFactory" words="lang/stopwords_en.txt" ignoreCase="true"/>
          <filter class="solr.LowerCaseFilterFactory"/>
          <filter class="solr.EnglishPossessiveFilterFactory"/>
          <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
          <filter class="solr.PorterStemFilterFactory"/>
        </analyzer>
        <analyzer type="query">
          <tokenizer class="solr.StandardTokenizerFactory"/>
          <filter class="solr.SynonymFilterFactory" expand="true" ignoreCase="true" synonyms="synonyms.txt"/>
          <filter class="solr.StopFilterFactory" words="lang/stopwords_en.txt" ignoreCase="true"/>
          <filter class="solr.LowerCaseFilterFactory"/>
          <filter class="solr.EnglishPossessiveFilterFactory"/>
          <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
          <filter class="solr.PorterStemFilterFactory"/>
        </analyzer>
      </fieldType>