使用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 3 1 4 10 8这样的数字对应于得分总和。 / p>
我使用的代码:
.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中的错误吗?
答案 0 :(得分:0)
match
查询为每个匹配的查询返回基于Lucene scoring formula (TF-IDF ish)的小数分数 - 然后乘以您在查询中提供的提升。
当查询包含时,这实际上对您有利 多个匹配术语(或多个扩展术语匹配时)。
对于您正在实施的更简单的评分策略,您需要使用Constant Score Queries 将过滤器包装在您的bool查询中。这将允许您为每个匹配条件返回常量分数。
更新:即使使用常量得分查询,由于查询规范化,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个也用作filter
查询的初始function_score
子句,因此无需对整个集合进行评分。 (一个标准被省略为过滤冗余 - 因为100%的语音术语匹配是50%语音术语匹配的子集)
答案 1 :(得分:0)
使用此代码并使用constantScoreQuery再次为我提供浮点数:(
QueryBuilder boolQ = boolQuery() 。应该(constantScoreQuery(termsSyn).boost(1))
。应该(constantScoreQuery(termsPhon).boost(7)) 。应该(constantScoreQuery(termsText).boost(15));
sqb.setQuery(boolQ);