愚者求师之过,智者从师之长。

ScoreScript脚本打分

Elasticsearch | 作者 QuincyXuHa | 发布于2023年03月02日 | 阅读数:3610

es版本:7.10.2
目的:重写打分规则,想要保证搜索字符串在原始字符串越前,排序就约靠前。
做法:核心是实现ScoreScript接口,主要是获取postion。代码如下:
@Override
public void setDocument(int docid) {
super.setDocument(docid);
try {
// 根据docid和field获取terms的信息,这里会取到多个term。实现见:CompressingTermVectorsReader
Terms terms = ctx.reader().terms(field);
// Terms terms = ctx.reader().getTermVector(docid, field);
logger.info("ctx={},docid={}, terms={}", ctx, docid,terms);
if (terms != null) {
for (String query : queryList) {
String term = getFirstMatchStr(query);
TermsEnum termsEnum = terms.iterator();
for (int i = 0; i < terms.size(); i++) {
// 遍历
String termOrigin = termsEnum.next().utf8ToString();
PostingsEnum postings = termsEnum.postings(null, PostingsEnum.ALL);
postings.nextDoc();
if (termOrigin.startsWith(term)) {
int position = postings.nextPosition();
if (position < firstMatchPosition) {
termDesc.add("curFirstPosition=" + firstMatchPosition + "命中term=" + termOrigin + position);
firstMatchPosition = position + 1;
}
// 检查到最靠前匹配的分词,结束遍历
break;
}
}
}
}
} catch (IOException e) {
logger.error("docid:{},field:{},query:{},get payload error!,stack:{}", docid, field, queryList, e);
}
}
但这样我发现所有的doc的firstMatchPosition都是一样的。比如小火花和小花,搜索花的时候计算出来的firstMatchPosition都是1。不知道哪里获取不对
已邀请:

QuincyXuHa - 90后

赞同来自:

现在发现:
Terms terms = ctx.reader().terms(field);
这个返回的结果在本地是当前doc字段的内容,在qa集群上是整个索引的doc内容,这是咋回事

QuincyXuHa - 90后

赞同来自:

找到原因了。。。。是我自己的问题,
ScoreScript的属性初始化直接放在属性上了,应该放在setDocument里面的,保证每次处理doc的时候都是初始化值而不是之前的值。

Ombres

赞同来自:

Terms terms = ctx.reader().terms(field); 获取的就是整个LeafReader 所有的terms吧?
 
常规用法是获取到term的postings,然后postings.advance(docid),再进行相关操作。

另外感觉很多情况下性能会比较差啊,如果LeafReader中term较多,对每篇命中的文章过一遍所有的term。
 

要回复问题请先登录注册