Elasticsearch-57-搜索联想

准备工作

删除之前的my_index

1
DELETE /my_index

然后再添加几条测试用的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
POST /my_index/my_type/1
{
"title":"hello world"
}

POST /my_index/my_type/2
{
"title":"hello we"
}

POST /my_index/my_type/3
{
"title":"hello win"
}

POST /my_index/my_type/4
{
"title":"hello wind"
}

POST /my_index/my_type/5
{
"title":"hello dog"
}

POST /my_index/my_type/6
{
"title":"hello cat"
}

搜索联想

比如说我们在Google的搜索框中输入了elasti,搜索框下面可能会出来elasticsearch, elasticsearch权威指南等这些信息.

我们可以用match_phrase_prefix来实现这个效果,原理和match_phrase类似,唯一的区别就是会把最后一个term作为前缀去搜索.

比如我们搜索hello w, hello就是去进行match,搜索对应的document,最后一个term是w,w就会被作为前缀,去扫描整个倒排索引,找到所有的w开头的document,然后找到既包含hello又包含w开头的document,根据你的slop去计算,看在slop范围内,能不能让hello w,正好跟document中的hello和w开头的单词的position相匹配

指定slop的话,也是只会将最后一个term作为前缀

max_expansions

默认情况下,前缀搜索要扫描所有倒排索引中的document,按时这样性能太差了,可以使用max_expansions指定prefix最多匹配多少个document,超过这个数量就不继续匹配了,限定性能

语法

1
2
3
4
5
6
7
8
9
10
11
12
GET /my_index/my_type/_search
{
"query": {
"match_phrase_prefix": {
"title": {
"query": "hello w",
"slop":10,
"max_expansions": 10
}
}
}
}

返回值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 4,
"max_score": 1.8798604,
"hits": [
{
"_index": "my_index",
"_type": "my_type",
"_id": "2",
"_score": 1.8798604,
"_source": {
"title": "hello we"
}
},
{
"_index": "my_index",
"_type": "my_type",
"_id": "4",
"_score": 1.8798604,
"_source": {
"title": "hello wind"
}
},
{
"_index": "my_index",
"_type": "my_type",
"_id": "1",
"_score": 0.51623213,
"_source": {
"title": "hello world"
}
},
{
"_index": "my_index",
"_type": "my_type",
"_id": "3",
"_score": 0.51623213,
"_source": {
"title": "hello win"
}
}
]
}
}

查询出来的都是包含hello和w是前缀的数据

在实际中,这种搜索也是尽量不要用,因为最后一个前缀始终要去扫描大量的索引,性能可能会很差