solr 的edismax与dismax比较与分析
edismax支持boost函数与score相乘作为,而dismax只能使用bf作用效果是相加,所以在处理多个维度排序时,score其实也应该是其中一个维度 ,用相加的方式处理调整麻烦。
而dismax的实现代码逻辑比较简单,看起来比较易理解,edismax是它的加强版,其实是改变了不少。。比如在以下:
先看看dismax的解析主要实现思路:
首先取出搜索字段名qf
将最终解析成一个BooleanQuery
先解析主mainQuery:
- 用户主要是搜索串的解析
- altQuery解析处理,看是否使用用户定义的后备搜索串
- PhraseQuery解析组装
看主要代码更清晰:
- @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,-语法元个数
- // defer escaping and only do if lucene parsing fails, or we need phrases
- // parsing fails. Need to sloppy phrase queries anyway though.
- List<Clause> 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就会失效
- 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
List<Clause>normalClauses =new ArrayList<Clause>(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获取短语查询的作法:
- protected Query getPhraseQuery(String userQuery, SolrPluginUtils.DisjunctionMaxQueryParser pp) throws ParseException {
- String userPhraseQuery = userQuery.replace("\"", "");
- return pp.parse("\"" + userPhraseQuery + "\"");
- }
下面是edismax的作法:
- private void addShingledPhraseQueries(final BooleanQuery mainQuery,
- final List<Clause> clauses,
- final Map<String,Float> fields,
- int shingleSize,
- final float tiebreaker,
- final int slop)
- throws ParseException {
- if (null == fields || fields.isEmpty() ||
- null == clauses || clauses.size() <= shingleSize )
- return;
- if (0 == shingleSize) shingleSize = clauses.size();
- final int goat = shingleSize-1; // :TODO: better name for var?
- StringBuilder userPhraseQuery = new StringBuilder();
- for (int i=0; i < clauses.size() - goat; i++) {
- userPhraseQuery.append('"');
- for (int j=0; j <= goat; j++) {
- userPhraseQuery.append(clauses.get(i + j).val);
- userPhraseQuery.append(' ');
- }
- userPhraseQuery.append('"');
- userPhraseQuery.append(' ');
- }
- ExtendedSolrQueryParser pp =
- new ExtendedSolrQueryParser(this, IMPOSSIBLE_FIELD_NAME);
- pp.addAlias(IMPOSSIBLE_FIELD_NAME, tiebreaker, fields);
- pp.setPhraseSlop(slop);
- pp.setRemoveStopFilter(true); // remove stop filter and keep stopwords
- pp.makeDismax = true;
- pp.minClauseSize = 2;
- Query phrase = pp.parse(userPhraseQuery.toString());
- if (phrase != null) {
- mainQuery.add(phrase, BooleanClause.Occur.SHOULD);
- }
- }
edismax技术另一个重要的boost查询,
boost查询也是不会影响搜索结果数,但是影响排序,主要作用是将最后得分以相乘的方式作用于score,函数的解析跟bf差不多。
- //
- // create a boosted query (scores multiplied by boosts)
- //
- Query topQuery = query;
- multBoosts = solrParams.getParams("boost");
- if (multBoosts!=null && multBoosts.length>0) {
- List<ValueSource> boosts = new ArrayList<ValueSource>();
- for (String boostStr : multBoosts) {
- if (boostStr==null || boostStr.length()==0) continue;
- Query boost = subQuery(boostStr, FunctionQParserPlugin.NAME).getQuery();
- ValueSource vs;
- if (boost instanceof FunctionQuery) {
- vs = ((FunctionQuery)boost).getValueSource();
- } else {
- vs = new QueryValueSource(boost, 1.0f);
- }
- boosts.add(vs);
- }
- if (boosts.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方法如下:
- 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.csdn.net/duck_genuine/article/details/8060026
solr 的edismax与dismax比较与分析的更多相关文章
- solr 使用edismax来控制评分
如何控制评分 如果设置了sort字段,那么将会按照sort字段的顺序返回结果. 如果没有设置sort字段,那么将会根据相关度打分来排序.也就是说,相关度更高的排在前面. 如何来定制适合自身业务的排序打 ...
- solr 请求参数过长报错,Solr配置maxBooleanClauses属性不生效原因分析
博客分类: 上次已经写过一篇关于solr中,查询条件过多的异常的文章,这次在总结扩展一下: 有时候我们的查询条件会非常多,由于solr的booleanquery默认设置的条件数为1024,所以超过 ...
- solr入门之权重排序方法初探之使用edismax改变权重
做搜索引擎避免不了排序问题,当排序没有要求时,solr有自己的排序打分机制及sorce字段 1.无特殊排序要求时,根据查询相关度来进行排序(solr自身规则) 2.当涉及到一个字段来进行相关度排序时, ...
- Solr Dismax查询解析器-深入分析
Solr 支持多种查询解析,给搜索引擎开发人员提供灵活的查询解析.Solr 中主要包含这几个查询解析器:标准查询解析器.DisMax 查询解析器,扩展 DisMax 查询解析器(eDisMax) Di ...
- [solr] - defType - 查询权重排序
Solr的defType有dismax/edismax两种,这两种的区别,可参见:http://blog.csdn.net/duck_genuine/article/details/8060026 下 ...
- solr defType查询权重排序
Solr的defType有dismax/edismax两种,这两种的区别,可参见:http://blog.csdn.net/duck_genuine/article/details/8060026 下 ...
- solr特点三: defType(查询权重排序)
Solr的defType有dismax/edismax两种,这两种的区别,可参见:http://blog.csdn.net/duck_genuine/article/details/8060026 e ...
- 初探solr搜索
solr是一个基于lucene的搜索引擎,lucene是一个全文检索引擎的架构.solr在此之上进行了封装完善,变成了一个很流行实用的搜索引擎,可以应对绝大部分的搜索需求.使用搜索引擎有以下几点好处: ...
- Solr系列五:solr搜索详解(solr搜索流程介绍、查询语法及解析器详解)
一.solr搜索流程介绍 1. 前面我们已经学习过Lucene搜索的流程,让我们再来回顾一下 流程说明: 首先获取用户输入的查询串,使用查询解析器QueryParser解析查询串生成查询对象Query ...
随机推荐
- 在JavaScript中进行文件处理,第一部分:基础
译注:原文是<JavaScript高级程序设计>的作者Nicholas Zakas写的,本翻译纯属为自己学习而做,仅供参考.原文链接:这里 很多年前,我在一次Goole面试被问到,如何在w ...
- [批处理]Oracle启动助手
前段日子开始学Oracle数据库,但是由于Oracle数据库的服务启动时间很长 所以机房的里面所有电脑的Oracle服务全部是被禁用的 所以每次上机使用的时候都要先进服务管理,然后把禁用更改为手动模式 ...
- java回收finalize方法的作用(编程思想)
清理:终结处理和垃圾回收 java有垃圾回收期负责回收无用对象占据的内存资源.但也有这种情况:假定你的对象(并非使用new)获得了一块“特殊”的内存区域,由于垃圾回收期只知道释放那些由new分配的内存 ...
- 互评Alpha版本
作业要求[https://edu.cnblogs.com/campus/nenu/2018fall/homework/2323] 队名:二次元梦之队 组长:刘莹莹 组员:周昊 潘世维 王玉潘 赵美增 ...
- c#实现对登陆信息的反馈,实现对网站登录密码的扫描
最近发现我们学校的电信上网改密码的页面很简单,没有验证码,于是我就很好奇,后来发现原来是我们学校的电信的那个改密码的页面有漏洞于是就可以通过扫描账号免费上网 原理就是对修改密码的页面进行POST请求 ...
- PostgreSQL锁级别及什么操作获取什么锁
表级锁 大多数的表级锁是由内置的 SQL 命令获得的,但他们也可以通过锁命令来明确获取.可使用的表级锁包括: 访问共享(ACCESS SHARE) - SELECT 命令可在查询中引用的表上获得该锁. ...
- c++的c风格字符串函数的实现
要注意使用断言判断传入的字符串非空. #include <cassert> //求字符串长度 size_t StrLen(const char *str) { assert(str != ...
- Linux运维学习笔记-软硬链接知识总结
文件链接 硬链接,通过索引节点来进行链接 硬链接原理图 硬链接的创建: 直接执行命令“ln 源文件 硬链接文件”,即可完成创建硬链接. 硬链接知识小结: 1.具有相同Inode节点号的多个文件是互 ...
- nginx: [emerg] "fastcgi_pass" directive is duplicate in /etc/nginx/sites-enabled/default:57
/************************************************************************************************ * ...
- postgresql PL/pgSQL—存储过程结构和变量声明
ref: https://www.postgresql.org/docs/9.6/static/plpgsql-structure.html 一. 函数结构 CREATE FUNCTION somef ...