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

[经验分享] solr 的edismax与dismax比较与分析

[复制链接]

尚未签到

发表于 2015-7-18 12:46:55 | 显示全部楼层 |阅读模式
  edismax支持boost函数与score相乘作为,而dismax只能使用bf作用效果是相加,所以在处理多个维度排序时,score其实也应该是其中一个维度 ,用相加的方式处理调整麻烦。
  而dismax的实现代码逻辑比较简单,看起来比较易理解,edismax是它的加强版,其实是改变了不少。。比如在以下:
  

  先看看dismax的解析主要实现思路:
  首先取出搜索字段名qf
  将最终解析成一个BooleanQuery
  先解析主mainQuery:
  

  • 用户主要是搜索串的解析
  • altQuery解析处理,看是否使用用户定义的后备搜索串
  • PhraseQuery解析组装

再解析bq查询,主要是额外加分的查询,不会影响搜索结果数,只会影响排序


再则是bf解析,函数搜索最后会以加的方式作用于文档评分

  
  看主要代码更清晰:
  

  



[java] viewplaincopy

  • @Override  
  • public Query parse() throws ParseException {  
  •   SolrParams solrParams = SolrParams.wrapDefaults(localParams, params);  
  •   
  •   queryFields = SolrPluginUtils.parseFieldBoosts(solrParams.getParams(DisMaxParams.QF));  
  •   if (0 == queryFields.size()) {  
  •     queryFields.put(req.getSchema().getDefaultSearchFieldName(), 1.0f);  
  •   }  
  •    
  •   /* the main query we will execute.  we disable the coord because
  •    * this query is an artificial construct
  •    */  
  •   BooleanQuery query = new BooleanQuery(true);  
  •   
  •   boolean notBlank = addMainQuery(query, solrParams);  
  •   if (!notBlank)  
  •     return null;  
  •   addBoostQuery(query, solrParams);  
  •   addBoostFunctions(query, solrParams);  
  •   
  •   return query;  
  • }  


  
  

  edismax的主要实现思路跟dismax差不多,以下是一些主要差别之处:
  edismax解析含有+,OR,NOT,-语法时,就会忽略掉使用MM。
  以下是主要代码实现:
  统计搜索串中+,OR ,NOT,-语法元个数
  




[java] viewplaincopy

  • // defer escaping and only do if lucene parsing fails, or we need phrases  
  •      // parsing fails.  Need to sloppy phrase queries anyway though.  
  •      List clauses = null;  
  •      int numPluses = 0;  
  •      int numMinuses = 0;  
  •      int numOR = 0;  
  •      int numNOT = 0;  
  •   
  •      clauses = splitIntoClauses(userQuery, false);  
  •      for (Clause clause : clauses) {  
  •        if (clause.must == '+') numPluses++;  
  •        if (clause.must == '-') numMinuses++;  
  •        if (clause.isBareWord()) {  
  •          String s = clause.val;  
  •          if ("OR".equals(s)) {  
  •            numOR++;  
  •          } else if ("NOT".equals(s)) {  
  •            numNOT++;  
  •          } else if (lowercaseOperators && "or".equals(s)) {  
  •            numOR++;  
  •          }  
  •        }  
  •      }  


  
/////当搜索串里包含有+,OR ,NOT,-这四种时候,mm就会失效  




[java] viewplaincopy

  • boolean doMinMatched = (numOR + numNOT + numPluses + numMinuses) == 0;  
  • (parsedUserQuery != null && doMinMatched) {  
  •   String minShouldMatch = solrParams.get(DisMaxParams.MM, "100%");  
  •   if (parsedUserQuery instanceof BooleanQuery) {  
  •     SolrPluginUtils.setMinShouldMatch((BooleanQuery)parsedUserQuery, minShouldMatch);  
  •   }  
  • }  


  








短语查询,先找出普通的查询,原来就是短语查询的、或者属于“OR”,“AND”,“NOT”,’TO‘类型的都不要。由于edismax支持解析符合lucene语法的搜索串,所以不像dismax那样,只需要简单的将搜索串去掉\“,然后加个“”括起来就行        

        // find non-field clauses
        ListnormalClauses =new ArrayList(clauses.size());
        for (Clauseclause :clauses) {
          if (clause.field !=null ||clause.isPhrase)continue;
          // check for keywords "AND,OR,TO"
          if (clause.isBareWord()) {
            String s =clause.val.toString();
            // avoid putting explict operators in the phrase query
            if ("OR".equals(s) ||"AND".equals(s) ||"NOT".equals(s) || "TO".equals(s))continue;
          }
          normalClauses.add(clause);
        }


        // full phrase...
        addShingledPhraseQueries(query, normalClauses, phraseFields, 0,
                                 tiebreaker,pslop);
        // shingles...
        addShingledPhraseQueries(query, normalClauses, phraseFields2, 2,  
                                 tiebreaker,pslop);
        addShingledPhraseQueries(query, normalClauses, phraseFields3, 3,
                                 tiebreaker,pslop);


////下面是dismax获取短语查询的作法:







[java] viewplaincopy

  • protected Query getPhraseQuery(String userQuery, SolrPluginUtils.DisjunctionMaxQueryParser pp) throws ParseException {  
  •   String userPhraseQuery = userQuery.replace("\"", "");  
  •   return pp.parse("\"" + userPhraseQuery + "\"");  
  • }  

下面是edismax的作法:  





[java] viewplaincopy

  • private void addShingledPhraseQueries(final BooleanQuery mainQuery,   
  •                                       final List clauses,  
  •                                       final Map fields,  
  •                                       int shingleSize,  
  •                                       final float tiebreaker,  
  •                                       final int slop)   
  •   throws ParseException {      
  •   if (null == fields || fields.isEmpty() ||   
  •       null == clauses || clauses.size() 1) {  
  •        ValueSource prod = new ProductFloatFunction(boosts.toArray(new ValueSource[boosts.size()]));  
  •        topQuery = new BoostedQuery(query, prod);  
  •      } else if (boosts.size() == 1) {  
  •        topQuery = new BoostedQuery(query, boosts.get(0));  
  •      }  
  •    }  

可以看到最后不是一个BooleanQuery,而是一个BoostedQuery。  
它就是简单处理子查询的分值再与函数查询的分值相乘返回 :主要的score方法如下:






[java] viewplaincopy

  • public float score() throws IOException {  
  •   float score = qWeight * scorer.score() * vals.floatVal(scorer.docID());  
  •   return score>Float.NEGATIVE_INFINITY ? score : -Float.MAX_VALUE;  
  • }  


  




转贴请声明来源:http://blog.iyunv.com/duck_genuine/article/details/8060026

运维网声明 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.iyunv.com/thread-87996-1-1.html 上篇帖子: Solr与HBase架构设计 下篇帖子: Solr 相关知识
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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