ES - 修改分词器及定制分词器
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ES - 修改分词器及定制分词器相关的知识,希望对你有一定的参考价值。
参考技术A 修改分词器设置
启用stardar停用词token filter,在stardard中stop token filter是默认被禁用的
定制化自己的分词器
在指定的type里面用定制化的分词器
ELK专栏之ES索引-04
ELK专栏之ES索引-04
索引Index入门
为什么我们要手动创建索引?
● 在生产上,我们需要自己手动建立索引和映射,是为了更好的管理索引,就像数据库的建表数据一样。
索引管理
创建索引
● 创建索引的语法:
PUT /index
"settings":...,
"mappings":
"properties":
...
,
"aliases":
"default_index":
示例:
● 创建索引:
PUT /my_index
"settings":
"number_of_shards": 1,
"number_of_replicas": 1
,
"mappings":
"properties":
"field1":
"type": "text"
,
"field2":
"type": "text"
,
"aliases":
"default_index":
插入数据:
PUT /my_index/_doc/1
"field1":"java",
"field2":"js"
查询数据:
GET /my_index/_doc/1
GET /default_index/_doc/1
查询索引
语法:查询索引:
GET /index
语法:查询索引中的映射信息
GET /index/_mapping
示例:
GET /my_index
GET /my_index/_mapping
GET /my_index/_settings
修改索引
语法:
PUT /index/_settings
"index" :
"number_of_replicas" : 5
示例:修改副本分片数
PUT /my_index/_settings
"index" :
"number_of_replicas" : 5
删除索引
语法:删除索引
DELETE /index
语法:删除多个索引
DELETE /index1,index2
DELETE /index*
语法:删除全部索引(危险)
DELETE /_all
示例:删除索引
DELETE /book
示例:删除多个索引
DELETE /book,my_index
示例:
DELETE /book*
示例:删除所有索引
DELETE /_all
为了安全起见,防止恶意删除索引,删除的时候必须指定索引名,我们可以在elasticsearch.yml中配置action.destructive_requires_name: true。
定制分词器
默认分词器
● 分词器有三个组件,分别为:character filter,tokenizer和token filter。
● 默认的分词器是:standard 分词器。
● standard tokenizer:以单词边界进行切分。
● standard token filter:什么都不做。
● lowercase token filter:将所有字母都转换为小写。
● stop token filter(默认被禁用):移除停用词,比如a、the、it等等。
修改分词器的位置
● 启用english停用词token filter:
PUT /my_index
"settings":
"analysis":
"analyzer":
"es_std":
"type":"standard",
"stopwords":"_english_"
使用标准分词器测试分词:
GET /my_index/_analyze
"analyzer": "standard",
"text": "a dog is in the house"
使用english停用词测试分词:
GET /my_index/_analyze
"analyzer": "es_std",
"text":"a dog is in the house"
定制自己的分词器
● 定制自己的分词器:
PUT /my_index
"settings":
"analysis":
"char_filter":
//&替换为and
"&_to_and":
"type": "mapping",
"mappings": ["&=> and"]
,
"filter":
//停用词--遇到这些词语会忽略分词
"my_stopwords":
"type": "stop",
"stopwords": ["the", "a"]
,
"analyzer":
//自定义分词器
"my_analyzer":
"type": "custom",
//字符过滤器
"char_filter": ["html_strip", "&_to_and"],
//以单词边界进行切分
"tokenizer": "standard",
//再进行过滤
"filter": ["lowercase", "my_stopwords"]
测试自定义分词器:
GET /my_index/_analyze
"analyzer": "my_analyzer",
"text": "tom&jerry are a friend in the house, <a>, HAHA!!"
设置字段使用自定义分词器:
PUT /my_index/_mapping/
"properties":
"content":
"type": "text",
"analyzer": "my_analyzer"
type底层结构及弃用原因
type是什么?
● type是一个Index中用来区分类似的数据的。这些类似的数据,可能有不同的fields,而且有不同的属性来控制索引和分词器的建立。
● field的value,在底层的Lucene中建立索引的时候,全都是opaque bytes类型,是不区分类型的。
● Lucene是没有type的概念的,在document(文档)中,实际上是将type作为document(文档)的field来存储的,即_type,ES通过_type来进行type的过滤和筛选。
ES中不同的type存储机制
● 一个Index中的多个type,实际上是放在一起存储的,因此同一个Index下,不能有多个type重名,因为那样是无法处理的。
● 比如:创建索引:
"goods":
"mappings":
"electronic_goods":
"properties":
"name":
"type": "string",
,
"price":
"type": "double"
,
"service_period":
"type": "string"
,
"fresh_goods":
"properties":
"name":
"type": "string",
,
"price":
"type": "double"
,
"eat_period":
"type": "string"
插入数据:
PUT /goods/electronic_goods/1
"name": "小米空调",
"price": 1999.0,
"service_period": "one year"
PUT /goods/fresh_goods/1
"name": "澳洲龙虾",
"price": 199.0,
"eat_period": "one week"
ES文档在底层的存储是这个样子的:
"goods":
"mappings":
"_type":
"type": "text",
"index": "false"
,
"name":
"type": "text"
"price":
"type": "double"
"service_period":
"type": "text"
,
"eat_period":
"type": "text"
那么插入的数据在底层的数据存储格式:
"_type": "electronic_goods",
"name": "小米空调",
"price": 1999.0,
"service_period": "one year",
"eat_period": ""
"_type": "fresh_goods",
"name": "澳洲龙虾",
"price": 199.0,
"service_period": "",
"eat_period": "one week"
type弃用的原因
● 同一个索引下,不同type的数据存储其他type的field的大量空值,会造成资源浪费。
● 所以,不同类型的数据,要放在不同的索引中。
● ES9中,将彻底删除type。
定制动态映射(dynamic mapping)
定制动态映射(dynamic mapping)策略
语法:
PUT /index
"settings": ...,
"mappings":
"dynamic": "xxx",
"properties":
"filed1":
"type": ""
,
"filed2":
"type": "",
"dynamic": "xxx"
,
...
,
"aliases":
"default_index":
dynamic:
- true,遇到陌生字段,就进行dynamic mapping,会自动帮助我们创建映射。
- false:新检测到的字段将被忽略。这些字段将不会被索引,因此将无法搜索,但仍将出现在返回的源字段中。这些字段不会添加到映射中,必须显示的添加新字段。
- strict:遇到陌生字段,就报错。
● 示例:
● 创建索引
PUT /my_index
"mappings":
"dynamic": "strict",
"properties":
"title":
"type": "text"
,
"address":
"type": "object",
"dynamic": "true"
测试插入数据
PUT /my_index/_doc/1
"title": "my article",
"content": "this is my article",
"address":
"province": "guangdong",
"city": "guangzhou"
如果是false情况下,content陌生字段不会被索引,我们在进行全局搜索时,不会搜索到content字段,但是如果搜索别的字段,搜索到该条记录时,还是会携带返回content字段的。
查询my_index的底层mapping映射,也可以发现其中并没有为content字段建立映射。
GET /my_index/_mapping
"my_index" :
"mappings" :
"dynamic" : "false",
"properties" :
"address" :
"dynamic" : "true",
"properties" :
"city" :
"type" : "text",
"fields" :
"keyword" :
"type" : "keyword",
"ignore_above" : 256
,
"province" :
"type" : "text",
"fields" :
"keyword" :
"type" : "keyword",
"ignore_above" : 256
,
"title" :
"type" : "text"
自定义动态映射(dynamic mapping)策略
- ES会根据传入的值,自动推断类型。
● 日期探测(Date Detection):默认会按照一定格式识别date,比如yyyy-MM-dd,但是如果某个field先过来一个"2019-11-11"的值,就会自动被dynamic mapping识别成date,后面如果在过来一个"hello world"之类的值,就会报错。可以手动关闭某个type的date detection,如果有需要,自己手动指定某个field为date类型。
● 语法:
PUT /index
"mappings":
"date_detection": false,
"properties":
"filed1":
"type": ""
,
"filed2":
"type": ""
,
...
示例:关闭日期探测
PUT /my_index
"mappings":
"date_detection": false,
"properties":
"title":
"type": "text"
,
"address":
"type": "object",
"dynamic": "true"
测试插入数据:
PUT /my_index/_doc/1
"title": "my article",
"content": "this is my article",
"address":
"province": "guangdong",
"city": "guangzhou"
,
"post_date":"2019-09-10"
● 自定义日期格式:dynamic_date_formats可以定制自己的格式。
● 语法:
PUT /index
"mappings":
"dynamic_date_formats": ["MM/dd/yyyy"],
"properties":
"filed1":
"type": ""
,
"filed2":
"type": ""
,
...
示例:自定义日期格式
PUT /my_index
"mappings":
"dynamic_date_formats": ["MM/dd/yyyy"]
测试插入数据:
PUT /my_index/_doc/1
"create_date": "09/25/2019"
● 数字探测(Numeric Detection):虽然JSON支持本机浮点和整数数据类型,但是某些应用程序或语言有时候可能将数字呈现为字符串。通常正确的解决方案是显示的映射这些字段,那么就可以启用数字检测(默认情况下禁用)来自动完成这些操作。
● 语法:
PUT /index
"mappings":
"numeric_detection": true,
"properties":
"filed1":
"type": ""
,
"filed2":
"type": ""
,
...
示例:开启数字探测
PUT /my_index
"mappings":
"numeric_detection": true
测试插入数据:
PUT /my_index/_doc/1
"my_float": "1.0",
"my_integer": "1"
定义自己的dynamic mapping template(动态映射模板)
● 动态映射模板允许我们自定义映射,这些映射可以应用到动态添加的字段。
● 语法:
PUT index
"mappings":
"dynamic_templates": [
"template_name":
... match conditions ...
"mapping": ...
,
...
]
- template_name:模板名称可以是任何字符串。
- match conditions:匹配条件,包括match_mapping_type、match、match_pattern、unmatch、path_match、path_unmatch。
- mapping:匹配字段应该使用的映射。
● 示例:
● 定制自己的映射模块:
PUT /my_index
"mappings":
"dynamic_templates": [
"en":
"match": "*_en",
"match_mapping_type": "string",
"mapping":
"type": "text",
"analyzer": "english"
]
插入数据:
PUT /my_index/_doc/1
"title": "this is my first article"
PUT /my_index/_doc/2
"title_en": "this is my first article"
搜索:
GET /my_index/_search?q=article
GET /my_index/_search?q=is
title没有匹配到任何的动态模块,默认就是standard分词器,不会过滤掉停用词,像is会进入到倒排索引,用is来搜索是可以搜索到的。
title_en匹配到了动态模块,就是english分词器,会过滤掉停用词,is这种停用词会被过滤掉,用is来搜索是搜索不到的。
模板写法:
PUT my_index
"mappings":
"dynamic_templates": [
"integers":
"match_mapping_type": "long",
"mapping":
"type": "integer"
,
"strings":
"match_mapping_type": "string",
"mapping":
"type": "text",
"fields":
"raw":
"type": "keyword",
"ignore_above": 256
]
模板参数:
"match": "long_*",
"unmatch": "*_text",
"match_mapping_type": "string"ELK专栏之ES索引-04
linux安装配置Elasticsearchkibanaik分词器及安装时遇到的问题