`
mozhenghua
  • 浏览: 318887 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Solr分词fieldType分词解析器设置错误导致查询错误

    博客分类:
  • solr
阅读更多

      今天在线上生产环境中碰到一个Solr的查询条件无法匹配到查询结果的问题,问题虽小,但是找到问题的过程确实比较周折,还好最终问题只是一层窗户纸,这里记录以下,以作备忘。

       问题是这样的,业务方告诉我有一个查询条件,没有办法匹配到目标记录。查询条件是:name:Y9砵仔糕吕托 收到问题,于是就开始了我的排错之路。

        首先,确认了一下name字段原始的文本字段是“Y9砵仔糕吕托”,对应的列的名称是 name,field type是一个自定义类型,类型为:

 

 <fieldType name="like" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="false" omitNorms="true" omitPositions="true">
      <analyzer type="index">
        <tokenizer class="solr.PatternTokenizerFactory" pattern=",\s*"/>
        <filter class="com.dfire.tis.solrextend.fieldtype.pinyin.AllWithNGramTokenFactory"/>
        <filter class="solr.StandardFilterFactory"/>
        <filter class="solr.TrimFilterFactory"/>
      </analyzer>
      <analyzer type="query">
        <tokenizer class="solr.PatternTokenizerFactory" pattern=",\s*"/>
        <filter class="solr.LowerCaseFilterFactory"/>
      </analyzer>
    </fieldType>

 这个filetype为了实现用户在搜索引擎上实现类似数据like查询的需求(当然solr上也能使用wildcardQuery,但是wildcardQuery比较耗费性能,数据量小应该没有问题,数据量大的话就要斟酌一下了)。

 

 

   AllWithNGramTokenFactory这个filter类型扩展了一下Solr默认的NGram类型,在分析的时候额外多加了一个整个field的字面量作为Term语汇单元。

     为了排查问题,先写了一个小程序,打印一下索引文件上name 字段term为“Y9砵仔糕吕托” 的记录到底存在不存在,写了以下一段代码:

private void readIteraveTerm() throws Exception {
        EmbeddedSolrServer server ;
		SolrCore core = server.getCoreContainer().getCore("supplygood");
		IndexReader rootreader = core.getSearcher().get().getIndexReader();
		LeafReader reader = null;
		Terms terms = null;
		TermsEnum termEnum = null;
		PostingsEnum posting = null;

		BytesRef term = null;
		int docid = 0;
		for (LeafReaderContext leaf : rootreader.getContext().leaves()) {
			reader = leaf.reader();
			liveDocs = reader.getLiveDocs();
			terms = reader.terms("name");

			termEnum = terms.iterator();
			int count = 0;
			String find = "Y9砵仔糕吕托";

			if ((termEnum.seekExact(new BytesRef(find)))) {

				System.out.println(termEnum.term().utf8ToString());
				posting = termEnum.postings(posting);
				do {

					docid = posting.nextDoc();
					System.out.println("docid:" + ("" + docid) + "_" + leaf.docBase);
				} while (docid != PostingsEnum.NO_MORE_DOCS);	
			}
		}
	}

 这段代码的执行结果证明,在索引上Y9砵仔糕吕托”为Term的记录是存在,那奇怪的是为什么,通过查询条件 name:Y9砵仔糕吕托 找不到对应的记录呢?

 

   又想起调试一下Solr的代码,最终底层Lucene是会通过 TermQuery这个类来执行查询的:

package org.apache.lucene.search;

public class TermQuery extends Query {
  .....
  public TermQuery(Term t) {
    term = Objects.requireNonNull(t);
    perReaderTermState = null;
  }
}

 所以在TermQuery类的构造函数上加了一个调试断点,启动程序进行条件,看看构造函数上传入的参数Term到底是一个什么值,结果看到的构造函数参数为“y9砵仔糕吕托”,奇怪,怎么大写的Y变成小写了。然后通过“y9砵仔糕吕托”到索引上找果然是没有这个Term作为的记录的,然后再看了一下Schema的fieldType,果然在query的分析配置中有<filter class="solr.LowerCaseFilterFactory"/>这个配置项,也就是说在查询阶段,会将name列中含有的大写字母统统转化成小写字母,而在索引生成的时候并没有做这大写转小写的操作,所以很自然的就会发生本文一开头说的问题。

  将FiledType改成下面这个样子就好了:

  <fieldType name="like" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="false" omitNorms="true" omitPositions="true">
      <analyzer type="index">
        <tokenizer class="solr.PatternTokenizerFactory" pattern=",\s*"/>
        <filter class="com.dfire.tis.solrextend.fieldtype.pinyin.AllWithNGramTokenFactory"/>
        <filter class="solr.LowerCaseFilterFactory"/>
        <filter class="solr.TrimFilterFactory"/>
      </analyzer>
      <analyzer type="query">
        <tokenizer class="solr.PatternTokenizerFactory" pattern=",\s*"/>
        <filter class="solr.LowerCaseFilterFactory"/>
      </analyzer>
    </fieldType>

 在analyzer中也加了一个<filter class="solr.LowerCaseFilterFactory"/>过滤器问题就解决了,哈哈酷

 

 

分享到:
评论

相关推荐

    支持solr 5.3.0的IKAnalyzer中文分词器

    IKAnalyzer中文分词器本身已经不支持最新的solr 5,集成到solr中分词会报错,这里将解决了solr 5支持问题的最新IK包共享出来,希望能帮到各位! 附上IK在schema.xml中的配置: &lt;fieldType name="text_ik" class=...

    solr6对应的IKAnalyzer分词器

    solr6对应的IKAnalyzer分词器jar包,使用方法: 1. 添加分词器的jar文件:在文件夹`contrib`下新建一个文件夹`rd-lib`,并将`IKAnalyzer2012_u6.jar`拷贝进来,这个文件夹用来存放第三方jar文件,后面做数据导入时候...

    solr5.x(含5.4)可用的ikanalyzer中文分词

    solr5.x(含5.4)可用的ikanalyzer中文分词 &lt;fieldType name="text_ik" class="solr.TextField"&gt; &lt;analyzer type="index"&gt; &lt;analyzer type="query"&gt; &lt;/fieldType&gt;

    支持Spring-data-solr1.5的ik分词器,同义词

    支持Spring-data-solr1.5的ik分词器,并且修改了代码,添加一个新的类,用于支持同义词,目前可以同时支持分词和同义词的功能。 修改 managed-schema,添加 &lt;fieldType name="text_lk" class="solr.TextField"&gt; ...

    IKAnalyzer5.2.1src增加连续数字、字母、英语智能分词支持solr5.x以上、lucence5.x以上版本

    配置文件:&lt;fieldType name="text_ik" class="solr.TextField"&gt; &lt;analyzer type="index"&gt; &lt;filter class="solr.LowerCaseFilterFactory"/&gt; &lt;filter class="solr.TrimFilterFactory"/&gt; &lt;analyzer ...

    IKAnalyzer5.2.1增加连续数字、字母、英语智能分词支持solr5.x以上、lucence5.x以上版本

    配置文件:&lt;fieldType name="text_ik" class="solr.TextField"&gt; &lt;analyzer type="index"&gt; &lt;filter class="solr.LowerCaseFilterFactory"/&gt; &lt;filter class="solr.TrimFilterFactory"/&gt; &lt;analyzer ...

    IKAnalyzer-solr4.x-update.zip

    &lt;fieldType name="text_ik" class="solr.TextField"&gt; &lt;!-- 使用智能分词 --&gt; &lt;analyzer type="index" class="org.wltea.analyzer.lucene.NotUseSmartIKAnalyzer"/&gt; &lt;!-- 使用智能分词 --&gt; &lt;analyzer type...

    ik对应的7.x分词器

    solr7以前的版本对于中文分词支持不好,通常会用IK分词器。对于solr7,可以直接使用提供的分词器。 二、solr7中文分词器使用步骤 1、复制lucene-analyzers-smartcn-7.2.0.jar(在contrib/analysis-extras/lucene-...

    IKAnalyzer分词器 下载IKAnalyzer2012FF_u1.jar

    IKAnalyzer分词器版本 2012 兼容Lucene3.3以上版本 ...--查询时候的分词器--&gt; &lt;analyzer type="query" isMaxWordLength="true" class="org.wltea.analyzer.lucene.IKAnalyzer"/&gt; &lt;/fieldType&gt;

    中文拼音分词器

    针对中文进行修改的拼音分词器,很强大,支持首字母搜索、全拼搜索,首字母+全拼搜索!配置如下:&lt;fieldtype name="text_pinyin" class="solr.TextField"&gt; &lt;analyzer type="index"&gt; ...

    ik-analyzer-solr7.zip

    1.ik中文分词器适配最新版本solr7和solr8,下载后解压,将target下的ik-analyzer-7.7.1.jar包放入Solr服务的`Jetty`或`Tomcat`的`webapp/WEB-INF/lib/`目录下。 2.将`resources`目录下的5个配置文件放入solr服务的`...

    中文分词器IK Analyzer 2012FF_hf1

    配置中文分词器的fieldType: &lt;fieldType name="text_ik" class="solr.TextField"&gt; &lt;analyzer type="index" isMaxWordLength="false" class="org.wltea.analyzer.lucene.IKAnalyzer"/&gt; &lt;analyzer type="query" ...

    ik-analyzer-8.3.1分词插件.rar

    -- ik分词器 --&gt; &lt;fieldType name="text_ik" class="solr.TextField"&gt; &lt;analyzer type="index"&gt; &lt;filter class="solr.LowerCaseFilterFactory"/&gt; &lt;analyzer type="query"&gt; &lt;filter class="solr....

    ik-analyzer-solr5 jar包

    对于solr5.x系列中文分词器在solr中配置如下 &lt;fieldType name="text_ik" class="solr.TextField"&gt; &lt;analyzer type="index" useSmart="false" class="org.wltea.analyzer.lucene.IKAnalyzer"/&gt; &lt;analyzer type=...

    IKAnalyzer2012FF_u1.jar

    IKAnalyzer分词器版本 2012 兼容Lucene3.3以上版本 ...--查询时候的分词器--&gt; &lt;analyzer type="query" isMaxWordLength="true" class="org.wltea.analyzer.lucene.IKAnalyzer"/&gt; &lt;/fieldType&gt;

    ansj分词jar包

    &lt;fieldType name="text_ansj" class="solr.TextField" positionIncrementGap="100"&gt; &lt;analyzer type="index"&gt; &lt;analyzer type="query"&gt; &lt;/fieldType&gt; &lt;field name="POI_NAME" type="text_ansj" indexed...

    mmseg4j2.0

    &lt;fieldtype name="textComplex" class="solr.TextField" positionIncrementGap="100"&gt; &lt;tokenizer class="com.chenlb.mmseg4j.solr.MMSegTokenizerFactory" mode="complex" dicPath="dic"/&gt; &lt;/fieldtype&gt; ...

    Solr的基本使用

    schema.xml,在SolrCore的conf目录下,它是Solr数据表配置文件,它定义了加入索引的数据的数据类型的。主要包括FieldTypes、Fields和其他的一些缺省设置。...通过使用solr查询要看出返回给客户端是数组:Fieldtype:

    IKAnalyzer2012FF_u1

    2、将IKAnalyzer.cfg.xml、stopword.dic拷贝到需要使用分词器的core的conf(盘符:\solr\server\solr\WEB-INF\classes)下面(注意:如果没有classe文件夹自己创建一个classes文件夹,方便配置自己的定义的词库) ...

Global site tag (gtag.js) - Google Analytics