MatchQuery是Elasticsearch中一种比较复杂的Query,在查询时会先被改写成一些低级Query的组合。
// TODO
MatchQuery改写流程的入口: org.elasticsearch.index.search.MatchQuery.MatchQueryBuilder.createFieldQuery(…)
其中主要调用了父类的实现:org.apache.lucene.util.QueryBuilder.createFieldQuery(…)
第一步,使用Analyzer对text进行分词,遍历分词结果TokenStream,计算出以下4个值:
int numTokens = 0;
int positionCount = 0;
boolean hasSynonyms = false;
boolean isGraph = false;
stream.reset();
while (stream.incrementToken()) {
numTokens++;
int positionIncrement = posIncAtt.getPositionIncrement();
if (positionIncrement != 0) {
positionCount += positionIncrement;
} else {
hasSynonyms = true;
}
int positionLength = posLenAtt.getPositionLength();
if (enableGraphQueries && positionLength > 1) {
isGraph = true;
}
}
quoted参数可以控制当positionLength>1时,是改写成PhraseQuery还是多个TermQuery组合成的BooleanQuery。
一般的MatchQuery中,quoted都为false,因此这里只重点分析quoted=false的情况
当token数量为1时,走analyzeTerm分支,此时MatchQuery被简单的改写成TermQuery
numTokens>1
isGraph = false
quoted=false
positionCount = 1
分词结果中有多个词,但只有1个位置,说明是多个同义词的情况,此时改写成SynonymQuery
例如,有同义词配置如下:
fast, speedy, kuai
使用如下查询时:
"match": {
"goodsTitle": "kuai"
}
numTokens>1
isGraph==false
quoted=false
positionCount>1
词数>1, position数也大于1,但是不是图,即不存在positionLength>1的情况,所有的positionLength都等于1
例如:有同义词配置如下:
fast, speedy
使用如下查询时:
"match": {
"goodsTitle": "fast wi fi network"
}
一个BooleanQuery下4个子句,其中一个SynonymQuery,3个TermQuery, 4个子句都是SHOULD关系。
numTokens>1
isGraph=true
quoted=false
这种情况下,分词的结果被视作是一张图, analyzeGraphBoolean流程如下:
例如:有同义词配置如下:
wi fi network, re dian
has down, wan cheng
(必须使用SynonymGraphFilter, 且expand=true)
使用如下查询时:
"match": {
"goodsTitle": "fast wi fi network has down"
}
在MatchQuery全部改写完成之后,会应用minimum_should_match参数。
入口在org.elasticsearch.index.query.MatchQueryBuilder.doToQuery(…)
......
Query query = matchQuery.parse(type, fieldName, value);
return Queries.maybeApplyMinimumShouldMatch(query, minimumShouldMatch);
MatchQuery的minimum_should_match参数只会被应用到最外层的BooleanQuery上。
minimum_should_match配置参考:
https://www.elastic.co/guide/en/elasticsearch/reference/5.6/query-dsl-minimum-should-match.html
将一个BooleanQuery中的所有Should子句的总数记作optionalClauses
类型 | 举例 | 描述 |
---|---|---|
整数 | 3 | 至少需要匹配3个should子句 |
负整数 | -2 | 至少需要匹配(optionalClauses-2)个should子句 |
百分比 | 75% | 至少需要匹配75%*optionalClauses个should子句 |
负百分比 | -25% | 至少需要匹配optionalClauses*(1-25%)个should子句 |
组合形式 | 3<90% | 如果optionalClauses<=3,则需要全部匹配 如果optionalClauses>3则需要匹配90% |
多重组合形式 | 4<75% 9<3 | 如果optionalClauses<=4,则需要全部匹配 如果4 |