Scoring
很重要的一点就是scoring本身没有太大的意义,它几乎是无意义的。一个文档的得分如果是0.25也许说明是很高的匹配度也许不是,它并不能说明什么。但是如果拿这个值与另一个非常相似的查询后的得分来比较的话,如果这个值是另一个的两倍,那就是说这个文档匹配查询两次。影响得分的因素有以下几个方面:
1.Term frequency---tf:文档中term出现的次数越多,得分越高。只针对查询的字段,和其它字段没关系。
2.Inverse document frequency-- idf:显然整个terms都在索引中是很少见的,但是它的得分也是最高的。文档频率是指文档中term出现的频率,也是基于每个字段。
3.co-ordination-- coord:查询条文匹配文档的数目越多,得分越高。所有强制匹配的条文必须匹配并且禁止的条文无匹配。可选条文不会影响得分。
4.Field length -- fieldNorm:匹配的字段越短,衡量索引中term的数目,匹配的文档的得分越高。例如:有一个字段值为smashing,另一个为smashing pumpkins,那么如果查询smashing的话,第一个得分要比第二个的高,因为第一个的字段长度更短。可以在schema文件中对field字段设置omitNorms属性来取消此控件的得分。
Query-time and index-time boosting
在查询时期或创建索引时都可以选择文档或字段级别的boosting,文档级别也就是指对所有字段执行boosting.schema文件中的field不能设置omitted。很少在创建索引时执行boosting,因为它不像查询那样灵活,也就是说需要更多的可预测性和可操作性。
Troubleshooting queries and scoring
一个很重要的工具就是使用debugQuery=on参数启用查询调试。考虑一个模糊查询a_name:Smashing~
我们可能直观的认为含有smashing的文档会得到最好得分,但是结果不是这样。因为如果匹配的文档中,如果查询字段的索引中的term少那么fieldNorms的值就会高,得分也会高,所以如果某个文档的索引中term比较多,那么很有可能得分会低。这种情况相当少见也可以认为这种情况不用优化。首先是模糊查询要小写,如果这样还是不行可以在schema文件中启用omitNorms。还有很多开发经验可以去试验例如:sweetspotsimilarity。
Dismax query parser(part 2)
这里提到的所有应用于dismax的也都适用于edismax,除非明确说明不适用。其实edismax就是打算在未来的发布版本中替代dismax的。
Lucene's DisjunctionMaxQuery
dismax可以查询多个field,并且每个field使用不同的boost。这个功能是由lucene的DisjunctionMaxQuery查询类型来支持。以下的讨论都是高级内容,不用刻意理解。只是记住dismax针对多个字段的查询会设置tie参数为0.1,这也是合理的选择。
举个例子。如果有一个简单查询rock。dismax可能会将它配置为DisjunctionMaxQuery为fieldA:rock^2 fieldB:rock^1.2 fieldC:rock^0.5,如果是boolean查询的话会跟这个查询有些不同,不同的地方也就是得分。类似的boolean查询的得分会基于这三个条文的总和,也就是DisjunctionMaxQuery会使用每一个的最大值。针对多个字段查询同一个term的情况,并且有些字段相对于另一些字段更重要,那么dismax应该更好的处理得分。API文档中的一个例子对这个特征的解释是,如果用户查询albino elephant,那么假如有一种情况是albino匹配一个字段,elephant匹配另一个字段,另一种情况是albino匹配两个字段,但是elephant没有一个匹配,那么dismax保证第一种情况的得分高于第二种情况。
另一个dismax得分的难题就是tie参数,tie的取值是0-1,默认是0,在实践中设置为0.1效果最好。
Boosting:Automatic phrase boosting
dismax会把phrase查询也就是引号引起来的查询进行转换,来改进得分。例如查询billy joel 会转换为+(billy joel) "billy joel"也就是说,如果一个文档包含billy joel,那么它不仅匹配原始term而且还匹配billy和joel,也就是匹配三个term,如果另一个文档不匹配短语billy joel,只是含有两个单词,那么lucene的得分算法会给第一个文档更高的得分。
Configuring automatic phrase boosting
automatic phrase boosting默认是不启用的。要使用的话可以使用pf参数,就是"phrase fields“的缩写。语法与qf相同。用相同的值作为开始并做相应的调整,从qf到pf变化通常的原因有以下几点:
1.使用不同的boost因素让短语增强的影响没有压倒性。一些经验可以来引导你做这些调整。
2.忽略那些只有一个term的字段。比如唯一标识字段。
3.忽略那些含有太大的文本值的字段,因为它可能全使查询效率大大降低。
4.使用一个具体相同值,但是使用不同analyzed的字段来替换这个字段,
同样的强烈推荐使用common-grams和shingling来提高执行效率。
Phrase slop configuration
phrase slop就是短语后跟一个波浪线和一个数字,就像这样"billy joel"~1
对于所有明确指定的短语查询dismax会自动添加两个参数来设置slop:qs和phrase boosting:ps,如果slop没有指定那么就相当于是0。
<str name="qs">1</str><str name="ps">0</str>
Partial phrase boosting
如果查询的是两个单词,那么edismax支持增强为连续的单词对,如果是三个单词,那么可以增强三倍。例如查询how now brown cow
会变为:
+(how now brown cow) "how now brown cow" "how now" "now brown" "brown cow" "how now brown" "now brown cow"
这个特征不会被ps参数影响,ps只应用于entire phrase boost。
Boosting:boost queries
dismax的bq参数可以用来指定多个查询,类似于automatic phrase boost。以类似的方式被添加到用户的查询中。记住一点,boosting只是用来影响q参数指定的用户查询所匹配到的那些文档的scoring。如果匹配的结果还匹配bq查询,那么这个文档的得分会更高。
(*:* -r_type:aaa)^2增强所有文档得分,但是除了aaa。
boost queries不如boost functions有用。
Boosting:boost functions
boost functions提供一个强大的功能就是使用用户设置的公式来对文档的score进行计算。这里所说的公式也就是solr的function queries,使用bf参数来操作score。edismax支持boost参数来进行function query。可以使用bf或boost多次。
<str name="boost">recip(map(rord(r_event_date),0,0,99000),1,95000,95000)</str>函数中不能有空格。bf和boost两个参数其实并没有以相同的方式解析。bf参数允许多种boost functions使用相同的参数,以空格分开,二者选一的话还是使用bf参数。还可以在bf参数中乘以因子在函数的结尾。比如^100