以下内容针对8.10版本的es
概念
首先,区分几个概念:
- Synonym Set:也就是同义词的数据部分,这部分可以通过API构建,也可以通过文件构建,官方推荐API
- Synonym Filter:在analyzer的filter(也叫token filter,与char_filter区分开就好)中使用,包括Synonym graph和Synonym(是的,filter就叫Synonym),建议使用前者,后者在一个词对一个词组的时候,可能有问题,参见:https://www.elastic.co/guide/en/elasticsearch/reference/current/token-graphs.html#token-graphs-invalid-token-graphs 和 https://www.elastic.co/guide/en/elasticsearch/reference/current/token-graphs.html#token-graphs-invalid-token-graphs ,因此【一定】要用synonym graph
- Analyzer:Analyzer包含Character filters(一般不用)、Tokenizer、以及Filter,也就是说,Analyzer包含filter,filter中可以有多个,其中一个可以是SynonymFilter,然后在其中指明SynonymSet(多种形式)
含同义词时的搜索逻辑
核心资料:https://www.elastic.co/guide/en/elasticsearch/reference/current/token-graphs.html
最核心的理解就是,一句话在搜索的时候,不仅仅是一串词,而是包含位置信息的,而某些词是可以跨越位置或在同一个位置的,因此同义词可以开展:
加了一个同义词quick=fast之后:
一个更核心的例子是:
假设domain name system
的一个同义词是dns
,那么一个query如果是domain name system is fragile
,那么他会变成:
因此可以同时匹配这两个文档:
1
2
dns is fragile
domain name system is fragile
应用同义词
demo场景
我们先构造一个demo场景,便于检验效果
域 | 值 |
---|---|
synonym | dns, domain name system |
document | d1: dns is fragile d2: domain name system is fragile d3: name system is fragile |
query | q1: dns q2: domain name system q3: name system q4: domain apple name system |
我们的预期是:
- q1命中d1、d2,证明同义词生效
- q2命中d1、d2,证明同义词生效,注意这里不要命中query_3,原因简单来说是我们已经知道
domain name system
这三个词是一个词组了,那么就不要拆开了 - q3命中d2、d3:因为是分散的几个词,和dns这个缩写没关系
- q4命中d2、d3:因为是分散的几个词,和dns这个缩写没关系
启动es
这一点直接参见https://www.elastic.co/guide/en/elasticsearch/reference/current/setup.html
要是只是简单看效果,可以参见:https://www.elastic.co/guide/en/elasticsearch/reference/current/run-elasticsearch-locally.html
构造synonym set
1
2
3
4
5
6
7
8
PUT _synonyms/my-synonyms-set
{
"synonyms_set": [
{
"synonyms": "dns, domain name system"
}
]
}
新建索引
实例如下
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
PUT /test-index
{
"settings": {
"analysis": {
"filter": {
"synonyms_filter": {
"type": "synonym_graph",
"synonyms_set": "my-synonyms-set",
"updateable": true
}
},
"analyzer": {
"my_index_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": ["lowercase"]
},
"my_search_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": ["lowercase", "synonyms_filter"]
}
}
}
},
"mappings": {
"properties": {
"text": {
"type": "text",
"analyzer": "my_index_analyzer",
"search_analyzer": "my_search_analyzer"
}
}
}
}
需要注意:
- 第6行到第10行定义了同义词,updateable必须是true,用的synonym set也是上面构造的
- 同义词只在search_analyzer生效
插入数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
POST /test-index/_doc
{
"text": "dns is fragile"
}
POST /test-index/_doc
{
"text": "domain name system is fragile"
}
POST /test-index/_doc
{
"text": "name system is fragile"
}
请求检验效果
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
GET test-index/_search
{
"query": {
"match": {
"text": {
"query": "dns"
}
}
}
}
GET test-index/_search
{
"query": {
"match": {
"text": {
"query": "domain name system"
}
}
}
}
GET test-index/_search
{
"query": {
"match": {
"text": {
"query": "name system"
}
}
}
}
GET test-index/_search
{
"query": {
"match": {
"text": {
"query": "domain apple name system"
}
}
}
}
执行后,会发现结果是符合我们预期的
我们主要看看q2 domain name system
为什么没有命中 d3 name system is fragile
1
2
3
4
5
6
7
8
9
10
11
GET test-index/_search
{
"query": {
"match": {
"text": {
"query": "domain name system"
}
}
},
"explain": true
}
然后我们会看到:
也就是说,domain name system
这三个词被当成了一个词组,因此单纯的 d3 name system is fragile
是不满足的。
增加同义词
如果我们希望新增一组同义词,即
1
2
3
4
5
6
7
8
PUT _synonyms/my-synonyms-set
{
"synonyms_set": [
{
"synonyms": "dns, domain name system, name system"
}
]
}
注意此时执行后,结果json里显示的是
"result": "updated"
,也就是说,是更新了现有同义词
此时我们再次执行q1,会发现三篇都被召回了。
如果我们想删除同义词(例如想删掉刚刚的name system
这个词),那么还是执行PUT,即
1
2
3
4
5
6
7
8
PUT _synonyms/my-synonyms-set
{
"synonyms_set": [
{
"synonyms": "dns, domain name system"
}
]
}
执行完再执行q1,就发现只有两篇召回了
参考资料
同义词核心文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/search-with-synonyms.html
analyze过程:https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis.html
指明搜索时使用的analyzer:https://www.elastic.co/guide/en/elasticsearch/reference/current/specify-analyzer.html#specify-search-analyzer
Token Graphs:尤其是关于同义词过程的可视化(也就是文中示意图的来源):https://www.elastic.co/guide/en/elasticsearch/reference/current/token-graphs.html
构造synonym set:https://www.elastic.co/guide/en/elasticsearch/reference/current/put-synonyms-set.html 更多:https://www.elastic.co/guide/en/elasticsearch/reference/current/synonyms-apis.html
构造SynonymGraphFilter:https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-synonym-graph-tokenfilter.html