[英]Elasticsearch request optimisation (strange script_score in Java API with bool query)
使用Elasticsearch 1.7.0,我想對文檔的文本字段進行查詢。 我需要獲取所有以下文件:
部分匹配(所有單詞都必須存在同義詞和模糊詞)
匹配模糊(所有單詞都必須存在+模糊+語音)
與匹配相關(需要找到單詞的50%)
我用3個Elasticsearch請求制作了一個Java程序,但是這些查詢太長了,因此我嘗試對所有查詢使用一個查詢:
{
"query":
{"bool": {
"should": [
{
"function_score": {
"boost_mode": "replace",
"query": {
"match": {
"text.syn": {
"query": "sorbone",
"operator": "and",
"fuzziness": 1,
"minimum_should_match": "100%"
}
}
},
"script_score": {
"script": "1"
}
}
},
{
"function_score": {
"boost_mode": "replace",
"query": {
"match": {
"text.phonetic": {
"query": "sorbone",
"operator": "and",
"fuzziness": 1,
"minimum_should_match": "100%"
}
}
},
"script_score": {
"script": "3"
}
}
},
{
"function_score": {
"boost_mode": "replace",
"query": {
"match": {
"text.phonetic": {
"query": "sorbone",
"operator": "or",
"minimum_should_match": "50%"
}
}
},
"script_score": {
"script": "7"
}
}
}
]
}
}
}
想法是對每個返回的文檔使用帶有特定分數的bool_query。 它運作良好,但是當我嘗試使用Java API進行轉換時,我得到了一個奇怪的分數,而是分數中有小數點,我正等着7 7 1 1 4 10 8這樣的數字對應於分數總和。
我使用的代碼:
.operator(org.elasticsearch.index.query.MatchQueryBuilder.Operator.AND)
.fuzziness(Fuzziness.ONE)
.minimumShouldMatch("100%");
QueryBuilder termsPhon = matchQuery("text.phonetic", "sorbonne")
.operator(org.elasticsearch.index.query.MatchQueryBuilder.Operator.AND)
.fuzziness(Fuzziness.ONE)
.minimumShouldMatch("100%");
QueryBuilder termsText = matchQuery("text", "sorbonne")
.operator(org.elasticsearch.index.query.MatchQueryBuilder.Operator.OR)
.minimumShouldMatch("50%");
QueryBuilder functionScorePartial = functionScoreQuery(termsSyn)
.add(ScoreFunctionBuilders.scriptFunction("1"))
.boostMode("replace");
QueryBuilder functionScoreFuzzy = functionScoreQuery(termsPhon)
.add(ScoreFunctionBuilders.scriptFunction("7"))
.boostMode("replace");
QueryBuilder functionScoreRelated = functionScoreQuery(termsText)
.add(ScoreFunctionBuilders.scriptFunction("15"))
.boostMode("replace")
;
QueryBuilder boolQ = boolQuery()
.should(functionScorePartial)
.should(functionScoreFuzzy)
.should(functionScoreRelated);
sqb.setQuery(boolQ);
SearchResponse response = sqb.execute().actionGet();
SearchHits hits = response.getHits();
當我查看生成的JSON時,我看到腳本函數的生成方式不同。 在原始的REST中,我有:
"functions" : [ {
"script_score" : {
"script" : "1"
}
} ],
"boost_mode" : "replace"
在生成的JSON中,沒有“功能”數組:
"script_score": {
"script": "1"
}
它是Elasticsearch Java API中的錯誤嗎?
match
查詢將根據每個匹配查詢的Lucene評分公式(TF-IDF ish)返回一個十進制分數- 然后將其乘以您在查詢中提供的提升。
當查詢包含多個匹配詞(或多個擴展詞匹配)時,這實際上可以為您帶來好處。
對於您要實施的更簡單的評分策略,您需要使用“固定分數查詢”將過濾器包裝在布爾查詢中。 這將允許您為每個匹配條件返回恆定分數 。
更新 :即使使用恆定分數查詢,由於查詢歸一化,OP也無法從bool
查詢中看到預期分數。 使用function_score
查詢的最初想法是正確的(用於實現完全自定義評分),但是還通過外部bool
查詢進行了查詢規范化。
避免這種規范化的方法是使function_score
查詢成為最外面的查詢(並使三個匹配條件成為評分函數):
{
"query": {
"function_score": {
"score_mode": "sum",
"boost_mode": "replace",
"filter": {
"bool": {
"should": [{
"query": {
"match": {
"text.syn": {
"query": "sorbone",
"operator": "and",
"fuzziness": 1,
"minimum_should_match": "100%"
}
}
}
}, {
"query": {
"match": {
"text.phonetic": {
"query": "sorbone",
"operator": "or",
"minimum_should_match": "50%"
}
}
}
}]
}
},
"functions": [{
"filter": {
"query": {
"match": {
"text.syn": {
"query": "sorbone",
"operator": "and",
"fuzziness": 1,
"minimum_should_match": "100%"
}
}
}
},
"weight": 1
}, {
"filter": {
"query": {
"match": {
"text.phonetic": {
"query": "sorbone",
"operator": "and",
"fuzziness": 1,
"minimum_should_match": "100%"
}
}
}
},
"weight": 3
}, {
"filter": {
"query": {
"match": {
"text.phonetic": {
"query": "sorbone",
"operator": "or",
"minimum_should_match": "50%"
}
}
}
},
"weight": 7
}]
}
}
}
請注意,這3個匹配條件中的2個也用作function_score
查詢的初始filter
子句,因此無需對整個集合進行評分。 (由於過濾的冗余,省略了一個標准,因為100%的語音字詞匹配是50%語音字詞匹配的子集)
將此代碼與constantScoreQuery結合使用,再次給了我分數的浮動數字:(
QueryBuilder boolQ = boolQuery().should(constantScoreQuery(termsSyn).boost(1))
.should(constantScoreQuery(termsPhon).boost(7)).should(constantScoreQuery(termsText).boost(15));
sqb.setQuery(boolQ);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.