# dis_max 实现 best fields 策略多字段搜索
增加 content 字段的测试数据
POST /forum/article/_bulk
{ "update": { "_id": "1"} }
{ "doc" : {"content" : "i like to write best elasticsearch article"} }
{ "update": { "_id": "2"} }
{ "doc" : {"content" : "i think java is the best programming language"} }
{ "update": { "_id": "3"} }
{ "doc" : {"content" : "i am only an elasticsearch beginner"} }
{ "update": { "_id": "4"} }
{ "doc" : {"content" : "elasticsearch and hadoop are all very good solution, i am a beginner"} }
{ "update": { "_id": "5"} }
{ "doc" : {"content" : "spark is best big data solution based on scala ,an programming language similar to java"} }
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 问题产生
搜索 title 或 content 中包含 java 或 solution 的帖子
GET /forum/article/_search
{
"query": {
"bool": {
"should": [
{"match": {
"title": "java solution"
}},
{
"match": {
"content": "java solution"
}
}
]
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
获取其中两条数据来分析下为什么会这样? 下面两条数据比较好描述
id 5 的 doc 中 content 包含了 solution 和 java,而 id 4 中只包含一个词语,应该是 id 5 得分高才对吧?
id=4,得分 0.7120095
"title": "this is java, elasticsearch, hadoop blog",
"content": "elasticsearch and hadoop are all very good solution, i am a beginner"
id=5,得分 0.56008905
"title": "this is spark blog",
"content": "spark is best big data solution based on scala ,an programming language similar to java"
1
2
3
4
5
6
7
2
3
4
5
6
7
这个就关系到 es 中的 should 得分计算规则有关系了。 大体的公式可以理解为这样:每个 query 得分相加 * matched query 数量 / 总 query 数量。
如 id 4 :
- title 中包含 java ; matched query 有得分,假设是 1.1
- content 中包含 solution;matched query 有得分,假设是 1.2
- matched query 数量:就是有得分的 query 数量,这里为 2
- 总 query 数量:should 中的 query 个数,这里为 2
(1.1 + 1.2) * 2 / 2 = 2.3
id 4:
- title :没有得分
- content 中包含 solution 和 java 有得分,假设是 2.3
- matched query 数量:就是有得分的 query 数量,这里为 1
- 总 query 数量:should 中的 query 个数,这里为 2
2.3 * 1 / 2 = 1.5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
这里就看出来了,id 5 得分变低了
# best fields 策略 和 dis_max
- best fields 策略:某一个 field 中匹配到了尽可能多的关键词,得分就高
- dis_max 语法:直接取多个 query 中,分数最高的那一个 query 的分数即可
有这两项保证,就能得到我们想要的结果了
GET /forum/article/_search
{
"query": {
"dis_max": {
"queries": [
{"match": {
"title": "java solution"
}},
{
"match": {
"content": "java solution"
}
}
]
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17