先是费话,说过要经常写博客的就要坚持。
最近学习solr,很好很强大。只是学习时间太短,很多没看明白,搭建好环境后,做好主从分布,并能做分布式搜索后,发现一个很严重的问题。就是在搜索短语时,结果很不理想。比如说
我搜“要加油呀”总是搜索不到结果,按理说是应能搜索到保护“加油”的doc才对的,使用debugQuery=on(http://localhost:8080/solr_slave1/select?q=%E8%A6%81%E5%8A%A0%E6%B2%B9&pf=f_contentt&debugQuery=on)查看只是看到了
<lst name="debug">
<str name="rawquerystring">要加油</str>
<str name="querystring">要加油</str>
<str name="parsedquery">PhraseQuery(f_content:"要 加油")</str>
<str name="parsedquery_toString">f_content:"要 加油"</str>
<lst name="explain"/>
<str name="QParser">LuceneQParser</str>
从上面可以看出分词是分对了,只是将“要加油”转成了“要 加油”,并且solr的处理方式也算是合情合理,将“要加油”分成“要”和“加油”的短语,然后查询索引中保护了这个短语的doc,只要在一个doc中的索引字段中包含了这个词就能搜索出来,当然这中间需要设置一些参数来让solr知道他们之间差多个slop也能知道。但我们想要的分词查询应该是这样的,http://localhost:8080/solr_slave1/select?q=%E8%A6%81%20%E5%8A%A0%E6%B2%B9&debugQuery=on。
<str name="rawquerystring">要 加油</str>
<str name="querystring">要 加油</str>
<str name="parsedquery">f_content:要 f_content:加油</str>
<str name="parsedquery_toString">f_content:要 f_content:加油</str>
因为研究solr时间不长,暂无解决方案,在网上搜了一下。说实话,网上关于solr的中文文档还真不多,很多都是简单的copy,而且没有深度的东西。
最后从http://blog.chenlb.com/2010/08/solr-use-custom-query-parser.html 这篇博客看出了端倪。这个作者在开源搜索引擎方面还是挺有见解的。
主要的解决方案就是说将PhraseQuery改为BooleanQuery,并且根据当前默然的operation来进行连接。
要实现这个功能需要重写SolrQueryParser的getFieldQuery方法。为什么?上面已经说过了。因为solr的默认处理方式是将你要搜索的短语能分词分成多个同一个位置的term时会采用BooleanQuery,其他的情况大都按照MultiPhraseQuery来处理,它会将分出的词都放入到这个MultiPhraseQuery中,只有同时满足这个MultiPhraseQuery要求的索引才能被搜索出来,具体可以详看代码QueryParse.java 中第568行protected Query getFieldQuery(String field, String queryText, boolean quoted) throws ParseException。很显然,我们中文的习惯一般情况下不能匹配这么精确,所以要采用BooleanQuery将能分割出来的词用OR的形式来处理,只要能搜索到部分,这个Doc就显示出来,这样才能得到我们想要的结果。
在结合着他的代码的同时,我稍作了修改。最终算是解决了这个问题。
具体步骤为
1.继承并实现QParserPlugin中的createParser方法来调用自己的lucene查询分析器。在这个插件中要是用自己的查询分析器。这个插件是要在solrconfig中使用的。
2.继承并重写QParser中的parse方法,来调用自己的Solr分析器。
3.继承并重写SolrQueryParser中的getFieldQuery方法,按照自己的思路来让solr处理分词方式。
4.将自己扩展的代码打成jar包。下面方式可以二选一。
1)修改solrconfig.xml中的<requestHandler name="search" class="solr.SearchHandler" default="true">。这个是solr服务器默然的请求处理器。
在<str name="echoParams">explicit</str>下面添加
<str name="defType">extlucene</str>
当然extlucene也需要在这个配置文件中声明。
<queryParser name="extlucene" class="com.sfbuy.solr.search.ExtLuceneQParserPlugin"/>
2) 直接使用request参数的形式,将http://localhost:8080/select?q=test&[b]defType=extLucene[/b]&.........
详细可参照代码
最近学习solr,很好很强大。只是学习时间太短,很多没看明白,搭建好环境后,做好主从分布,并能做分布式搜索后,发现一个很严重的问题。就是在搜索短语时,结果很不理想。比如说
我搜“要加油呀”总是搜索不到结果,按理说是应能搜索到保护“加油”的doc才对的,使用debugQuery=on(http://localhost:8080/solr_slave1/select?q=%E8%A6%81%E5%8A%A0%E6%B2%B9&pf=f_contentt&debugQuery=on)查看只是看到了
<lst name="debug">
<str name="rawquerystring">要加油</str>
<str name="querystring">要加油</str>
<str name="parsedquery">PhraseQuery(f_content:"要 加油")</str>
<str name="parsedquery_toString">f_content:"要 加油"</str>
<lst name="explain"/>
<str name="QParser">LuceneQParser</str>
从上面可以看出分词是分对了,只是将“要加油”转成了“要 加油”,并且solr的处理方式也算是合情合理,将“要加油”分成“要”和“加油”的短语,然后查询索引中保护了这个短语的doc,只要在一个doc中的索引字段中包含了这个词就能搜索出来,当然这中间需要设置一些参数来让solr知道他们之间差多个slop也能知道。但我们想要的分词查询应该是这样的,http://localhost:8080/solr_slave1/select?q=%E8%A6%81%20%E5%8A%A0%E6%B2%B9&debugQuery=on。
<str name="rawquerystring">要 加油</str>
<str name="querystring">要 加油</str>
<str name="parsedquery">f_content:要 f_content:加油</str>
<str name="parsedquery_toString">f_content:要 f_content:加油</str>
因为研究solr时间不长,暂无解决方案,在网上搜了一下。说实话,网上关于solr的中文文档还真不多,很多都是简单的copy,而且没有深度的东西。
最后从http://blog.chenlb.com/2010/08/solr-use-custom-query-parser.html 这篇博客看出了端倪。这个作者在开源搜索引擎方面还是挺有见解的。
主要的解决方案就是说将PhraseQuery改为BooleanQuery,并且根据当前默然的operation来进行连接。
要实现这个功能需要重写SolrQueryParser的getFieldQuery方法。为什么?上面已经说过了。因为solr的默认处理方式是将你要搜索的短语能分词分成多个同一个位置的term时会采用BooleanQuery,其他的情况大都按照MultiPhraseQuery来处理,它会将分出的词都放入到这个MultiPhraseQuery中,只有同时满足这个MultiPhraseQuery要求的索引才能被搜索出来,具体可以详看代码QueryParse.java 中第568行protected Query getFieldQuery(String field, String queryText, boolean quoted) throws ParseException。很显然,我们中文的习惯一般情况下不能匹配这么精确,所以要采用BooleanQuery将能分割出来的词用OR的形式来处理,只要能搜索到部分,这个Doc就显示出来,这样才能得到我们想要的结果。
在结合着他的代码的同时,我稍作了修改。最终算是解决了这个问题。
具体步骤为
1.继承并实现QParserPlugin中的createParser方法来调用自己的lucene查询分析器。在这个插件中要是用自己的查询分析器。这个插件是要在solrconfig中使用的。
2.继承并重写QParser中的parse方法,来调用自己的Solr分析器。
3.继承并重写SolrQueryParser中的getFieldQuery方法,按照自己的思路来让solr处理分词方式。
4.将自己扩展的代码打成jar包。下面方式可以二选一。
1)修改solrconfig.xml中的<requestHandler name="search" class="solr.SearchHandler" default="true">。这个是solr服务器默然的请求处理器。
在<str name="echoParams">explicit</str>下面添加
<str name="defType">extlucene</str>
当然extlucene也需要在这个配置文件中声明。
<queryParser name="extlucene" class="com.sfbuy.solr.search.ExtLuceneQParserPlugin"/>
2) 直接使用request参数的形式,将http://localhost:8080/select?q=test&[b]defType=extLucene[/b]&.........
详细可参照代码