再补充一条

自定义不拆分词的时候,里面不能出现“ ”(空格),否则,ik会把它拆分掉,比如你定了了 “蚂蚁 搬家”和“蚂蚁搬家” ,其中“蚂蚁 搬家”会被拆分,而“蚂蚁搬家”不会被拆分

实际上ik还会对类似“c++”等进行忽略,一个解决方案就是,把这些符号替换为文字,包括创建索引的时候和搜索进行拆词的时候。

后来发现也可以在ik/custom/my.dic里面写入c++,这样c++就不会被忽略,但是依然会被拆分,比如 定义“c++服务器开发工程师”为不拆分,依然会被拆分为“c++”和其他词


我在创建索引的时候

索引结构如下:

{
     "C_INDEX_APPKEYWORD": {
         "_all": {
             "analyzer": "ik_syno",
             "search_analyzer": "ik_smart",
             "term_vector": "no",
             "store": "false"
         },
         "properties": {
             "keyword": {
                 "type": "string",
                 "analyzer": "ik_smart",
                 "search_analyzer": "ik_smart"
             }
         }
     }
 }

我在搜索的时候,搜索语句如下

{
   "from" : 0,
   "size" : 1000,
   "query" : {
     "bool" : {
       "must" : [{
         "query_string" : {
           "query" : "网络",
           "fields" : [ "keyword" ],
           "analyzer" : "ik_smart"
         }
       } ]
     }
   }
 }


结果查询的时候_all的查询内容和指定查询"keyword"的内容就是差距很大,经过多方打探终于得到了答案,看上方的红色部分,实际上

ik_max_word 

ik_syno_smart= ik_smart 

也就是说创建索引的时候,指定了两个不同颗粒度的分词方式,结果是肯定是不一样的。附两份查到的资料和一份官方文档

官方
https:///guide/cn/elasticsearch/guide/current/mapping-analysis.html#mapping-analysis


 ik_syno 和 ik_syno_smart 、ik_max_word 和 ik_smart 关系



elasticsearch-analysis-ik分词器

2、配置ik同义词


Elasticsearch 自带一个名为 synonym 的同义词 filter。为了能让 IK 和 synonym 同时工作,我们需要定义新的 analyzer,用 IK 做 tokenizer,synonym 做 filter。听上去很复杂,实际上要做的只是加一段配置。

打开 /config/elasticsearch.yml 文件,加入以下配置:

1. index:  
2.   analysis:  
3.     analyzer:  
4.       ik_syno:  
5.           type: custom  
6.           tokenizer: ik_max_word  
7.           filter: [my_synonym_filter]  
8.       ik_syno_smart:  
9.           type: custom  
10.           tokenizer: ik_smart  
11.           filter: [my_synonym_filter]  
12.     filter:  
13.       my_synonym_filter:  
14.           type: synonym  
15.           synonyms_path: analysis/synonym.txt


以上配置定义了 ik_syno 和 ik_syno_smart 这两个新的 analyzer,分别对应 IK 的 ik_max_word 和 ik_smart 两种分词策略。根据 IK 的文档,二者区别如下:

  • ik_max_word:会将文本做最细粒度的拆分,例如「中华人民共和国国歌」会被拆分为「中华人民共和国、中华人民、中华、华人、人民共和国、人民、人、民、共和国、共和、和、国国、国歌」,会穷尽各种可能的组合;
  • ik_smart:会将文本做最粗粒度的拆分,例如「中华人民共和国国歌」会被拆分为「中华人民共和国、国歌」;

ik_syno 和 ik_syno_smart 都会使用 synonym filter 实现同义词转换。

3、创建/config/analysis/synonym.txt 文件,输入一些同义词并存为 utf-8 格式。例如

es搜索特殊符号搜不到 es搜索特殊符号搜不到了_es搜索特殊符号搜不到

到此同义词配置已经完成,重启ES即可,搜索时指定分词为ik_syno或ik_syno_smart。

创建Mapping映射。执行curl命令如下

1. curl -XPOST  http://192.168.1.99:9200/goodsindex/goods/_mapping -d'{  
2.   "goods": {  
3.     "_all": {  
4.       "enabled": true,  
5.       "analyzer": "ik_max_word",  
6.       "search_analyzer": "ik_max_word",  
7.       "term_vector": "no",  
8.       "store": "false"  
9.     },  
10.     "properties": {  
11.       "title": {  
12.         "type": "string",  
13.         "term_vector": "with_positions_offsets",  
14.         "analyzer": "ik_syno",  
15.         "search_analyzer": "ik_syno"  
16.       },  
17.       "content": {  
18.         "type": "string",  
19.         "term_vector": "with_positions_offsets",  
20.         "analyzer": "ik_syno",  
21.         "search_analyzer": "ik_syno"  
22.       },  
23.       "tags": {  
24.         "type": "string",  
25.         "term_vector": "no",  
26.         "analyzer": "ik_syno",  
27.         "search_analyzer": "ik_syno"  
28.       },  
29.       "slug": {  
30.         "type": "string",  
31.         "term_vector": "no"  
32.       },  
33.       "update_date": {  
34.         "type": "date",  
35.         "term_vector": "no",  
36.         "index": "no"  
37.       }  
38.     }  
39.   }  
40. }'


以上代码为 test 索引下的 article 类型指定了字段特征: title 、 content 和 tags 字段使用 ik_syno 做为 analyzer,说明它使用 ik_max_word 做为分词,并且应用 synonym 同义词策略; slug 字段没有指定 analyzer,说明它使用默认分词;而 update_date 字段则不会被索引。


elasticsearch 自定义索引 _all 设置规则


ElasticSearch的_all域

  ElasticSearch默认为每个被索引的文档都定义了一个特殊的域 - '_all',它自动包含被索引文档中一个或者多个域中的内容, 在进行搜索时,如果不指明要搜索的文档的域,ElasticSearch则会去搜索_all域。_all带来搜索方便,其代价是增加了系统在索引阶段对CPU和存储空间资源的开销。

       默认情况,ElasticSarch自动使用_all所有的文档的域都会被加到_all中进行索引。可以使用"_all" : {"enabled":false} 开关禁用它。如果某个域不希望被加到_all中,可以使用 "include_in_all":false。例如:

1. {  
2.    "person": {  
3.       "_all": { "enabled": true }  
4.       "properties": {  
5.          "name": {  
6.             "type": "object",  
7.             "dynamic": false,  
8.             "properties": {  
9.                "first": {  
10.                   "type": "string",  
11.                   "store": true,  
12.                   "include_in_all": false  
13.                },  
14.                "last": {  
15.                   "type": "string",  
16.                   "index": "not_analyzed"  
17.                }  
18.             }  
19.          },  
20.          "address": {  
21.             "type": "object",  
22.             "include_in_all": false,  
23.             "properties": {  
24.                "first": {  
25.                   "properties": {  
26.                      "location": {  
27.                         "type": "string",  
28.                         "store": true,  
29.                         "index_name": "firstLocation"  
30.                      }  
31.                   }  
32.                },  
33.                "last": {  
34.                   "properties": {  
35.                      "location": {  
36.                         "type": "string"  
37.                      }  
38.                   }  
39.                }  
40.             }  
41.          },  
42.          "simple1": {  
43.             "type": "long",  
44.             "include_in_all": true  
45.          },  
46.          "simple2": {  
47.             "type": "long",  
48.             "include_in_all": false  
49.          }  
50.       }  
51.    }  
52. }


查询时,_all和其它域一样使用:

1. GET /profiles/_search  
2. {  
3.     "query": {  
4.         "match": {  
5.            "_all": "food"  
6.         }  
7.     }  
8. }




或者在不提供搜索域的情况下,默认会搜索_all,例如:

1. GET /profiles/_search  
2. {  
3.     "query": {  
4.         "query_string": {  
5.             "query": "food"  
6.         }  
7.     }  
8. }