设为首页 收藏本站
查看: 1514|回复: 0

[经验分享] 解决solr搜索多词匹配度和排序方案

[复制链接]

尚未签到

发表于 2017-12-19 11:58:24 | 显示全部楼层 |阅读模式
  转载请标明出处:http://blog.csdn.net/hu948162999/article/details/47727159
  

  本文主要介绍了在短语、句子、多词查询中。solr在控制查询命中数量、之后再对结果集进行排序
  在solr中
默认是or 查询。也就是说:假设搜索q 中 分出来的词越多。所匹配的数量也就越多。
  如:搜索短语  “中国联想笔记本” ,分词结果:中国 、联想 、 笔记本。
  覆盖结果集:仅仅要文档中包括这3个随意词,都给返回。
  排序结果:依照solr的打分公式。默认匹配相关度最高的文档放在第一位。。简单的说。就是文档中。同一时候含有 中国
、联想 、 笔记本 分值最高。这样的需求一般能够满足部分的企业级搜索。
  可是:假设须要自己定义排序的话,问题就逐渐暴露了。
  通过requestHandler queryParser edismax 中的 df qf,通过字段的权重配置和 各个维度的积分模型之后,得出的排序。就不一定依照同一时候 含有 中国
、联想 、 笔记本优先级排序了。
  。有些仅仅包括 中国  这个词的优先级非常高 也有可能。这样的结果排序 明显不能理解和符合用户的意思。
  

  怎样合理的控制solr查询的命中的数量和质量???
  在上篇文章中,提到了两种关于solr 对短语、短句(非关键词)的搜索精度解决方式,solr控制多词联合查询命中的数量。
  可是上面攻克了返回精度的问题。
  可是设置mm匹配精度 或者全词匹配defaultOperator=“AND”。df和qf 自己定义的排序 就不起作用了。
  

  默认情况下,Solr查询语法仅仅有两种形式:关键词或者以空格分隔的关键词组。
  当查询英文时,英文本身就是以空格来区分词的,所以Solr就能直接获取英文词并组装Query。可是中文句子中间没有空格,Solr查询时把整个句子交给Query。然后由Query再依照Field来分词、查询。这样就丧失了DisMax中qf所能带来的优点。
  所以:思考了这么一种思路。对“中国联想笔记本”分词之后。对每一个词单元
中间接一个空格,就能够满足控制搜索词匹配度的前提下。提供自己定义排序。
  这个时候就须要重写lucene的默认的queryParser 。
  版本号:solr4.10.3
  solrconfig.xml代码
  

<span style=&quot;font-size:14px;&quot;><str name=&quot;defType&quot;>myparser</str></span>  

<span style=&quot;font-size:14px;&quot;> <!-- 自己定义queryParser -->
  <queryParser name=&quot;myparser&quot;>  
重写QParserPlugin和DisMaxQParser
  

<span style=&quot;font-size:14px;&quot;>package com.lubanec.util;  

  
import org.apache.solr.common.params.SolrParams;
  
import org.apache.solr.common.util.NamedList;
  
import org.apache.solr.request.SolrQueryRequest;
  
import org.apache.solr.search.QParser;
  
import org.apache.solr.search.QParserPlugin;
  


  
public>  

  public void init(NamedList args) {
  }
  

  public QParser createParser(String qstr, SolrParams localParams,
  SolrParams params, SolrQueryRequest req) {
  return new MyQParser(qstr, localParams, params, req);
  }
  
}
  
</span>
  

<span style=&quot;font-size:14px;&quot;>package com.lubanec.util;  

  
import java.io.StringReader;
  

  
import org.apache.lucene.analysis.Analyzer;
  
import org.apache.lucene.analysis.TokenStream;
  
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
  
import org.apache.solr.common.params.SolrParams;
  
import org.apache.solr.request.SolrQueryRequest;
  
import org.apache.solr.search.DisMaxQParser;
  
import org.slf4j.Logger;
  
import org.slf4j.LoggerFactory;
  


  
public>  private static Logger log = LoggerFactory.getLogger(MyQParser.class);
  

  public MyQParser(String qstr, SolrParams localParams, SolrParams params,
  SolrQueryRequest req) {
  super(qstr, localParams, params, req);
  Analyzer analyzer = req.getSchema().getQueryAnalyzer();
  if (null == analyzer)
  return;
  StringBuilder norm = new StringBuilder();
  
//log.info(&quot;before analyzer, qstr=&quot; + this.qstr);
  try {
  TokenStream ts = analyzer.tokenStream(req.getSchema().getDefaultSearchFieldName(), new StringReader(this.qstr));
  ts.reset();
  while (ts.incrementToken()) {
  CharTermAttribute termAttribute = ts.getAttribute(CharTermAttribute.class);
  
//              System.out.println(termAttribute.toString());
  norm.append(new String(termAttribute.toString())).append(&quot; &quot;);  
  }
  ts.end();
  ts.close();
  } catch (Exception ex) {
  log.info(&quot;Ex=&quot; + ex);
  }
  if (norm.length() > 0)
  this.qstr = norm.toString();
  
//log.info(&quot;after analyzer, qstr=&quot; + this.qstr);
  }
  

  
}
  
</span>
  

  最好的办法,就把默认的ExtendedDismaxQParser复制过来,加上本地代码。。保留dismax全部功能。
  例如以下:
DSC0000.jpg

  在ExtendedDismaxQParser构造方法中增加上面那部分代码;
  public ExtendedDismaxQParser(String qstr, SolrParams localParams, SolrParams params, SolrQueryRequest req) {  super(qstr, localParams, params, req);
  Analyzer analyzer = req.getSchema().getQueryAnalyzer();
  if (null == analyzer)
  return;
  StringBuilder norm = new StringBuilder();
  try {
  TokenStream ts = analyzer.tokenStream(req.getSchema()
  .getDefaultSearchFieldName(), new StringReader(this.qstr));
  ts.reset();
  while (ts.incrementToken()) {
  CharTermAttribute termAttribute = ts.getAttribute(CharTermAttribute.class);
  norm.append(new String(termAttribute.toString())).append(&quot; &quot;);
  }
  ts.end();
  ts.close();
  } catch (Exception ex) {
  ex.printStackTrace();
  }
  if (norm.length() > 0)
  this.qstr = norm.toString();
  config = this.createConfiguration(qstr,localParams,params,req);
  }
  
OK。。结束!

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-425684-1-1.html 上篇帖子: Solr - 无*.war版solr安装及配置 下篇帖子: HBase协处理器同步二级索引到Solr(续)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表