Elasticsearch由浅入深(十一)索引管理
索引的基本操作
- 创建索引
PUT /{index}
{
"settings": {},
"mappings": {
"properties": {
}
}
}创建索引示例:
PUT /my_index
{
"settings": {
"number_of_shards": ,
"number_of_replicas":
},
"mappings": {
"my_type":{
"properties": {
"my_field":{
"type": "text"
}
}
}
}
} - 修改索引
PUT /{index}/_settings
{
"setttings": {}
} PUT /my_index/_settings
{
"settings": {
"number_of_replicas": 1
}
} - 删除索引
DELETE /{index}
示例
DELETE /my_index
DELETE /index_one,index_two
DELETE /index_*
DELETE /_all删除索引API也可以通过使用逗号分隔列表应用于多个索引,或者通过使用_all或*作为索引应用于所有索引(小心!)。
要禁用允许通过通配符删除索引,或者将 elasticsearch.yml 配置中的_all设置action.destructive_requires_name设置为true。也可以通过群集更新设置api更改此设置。
修改分词器以及定义自己的分词器
Elasticsearch附带了各种内置分析器,无需进一步配置即可在任何索引中使用:
standard analyzer:
所述standard分析器将文本分为在字边界条件,由Unicode的文本分割算法所定义的。它删除了大多数标点符号,小写术语,并支持删除停用词。
Simple analyzer:
该simple分析仪将文本分为方面每当遇到一个字符是不是字母。然后全部变为小写
whitespace analyzer:
whitespace只要遇到任何空格字符 ,分析器就会将文本划分为术语。它不会进行小写转换。
stop analyzer:
该stop分析器是像simple,而且还支持去除停止词。
keyword analyzer:
所述keyword分析器是一个“空操作”分析器接受任何文本它被赋予并输出完全相同的文本作为一个单一的术语,也就是不会分词,进行精确匹配。
pattern analyzer:
所述pattern分析器使用一个正则表达式对文本进行拆分。它支持小写转换和停用字。
language analyzer:
Elasticsearch提供了许多特定于语言的分析器,如english或 french。
fingerprint analyzer:
所述fingerprint分析器是一种专业的指纹分析器,它可以创建一个指纹,用于重复检测。
修改分词器的设置
- 启动english停用词token filter
put /my_index
{
"settings": {
"analysis": {
"analyzer": {
"es_std":{
"type":"standard",
"stopwords":"_english_"
}
}
}
}
} - 测试分词
使用原来的standard分词# standard分词
GET /my_index/_analyze
{
"analyzer": "standard",
"text": "a dog is in the house"
}{
"tokens": [
{
"token": "a",
"start_offset": ,
"end_offset": ,
"type": "<ALPHANUM>",
"position":
},
{
"token": "dog",
"start_offset": ,
"end_offset": ,
"type": "<ALPHANUM>",
"position":
},
{
"token": "is",
"start_offset": ,
"end_offset": ,
"type": "<ALPHANUM>",
"position":
},
{
"token": "in",
"start_offset": ,
"end_offset": ,
"type": "<ALPHANUM>",
"position":
},
{
"token": "the",
"start_offset": ,
"end_offset": ,
"type": "<ALPHANUM>",
"position":
},
{
"token": "house",
"start_offset": ,
"end_offset": ,
"type": "<ALPHANUM>",
"position":
}
]
}使用原来的es_sted中的english分词
# english分词
GET /my_index/_analyze
{
"analyzer": "es_std",
"text": "a dog is in the house"
}{
"tokens": [
{
"token": "dog",
"start_offset": ,
"end_offset": ,
"type": "<ALPHANUM>",
"position":
},
{
"token": "house",
"start_offset": ,
"end_offset": ,
"type": "<ALPHANUM>",
"position":
}
]
}
定制自己的分词器
PUT /my_index
{
"settings": {
"analysis": {
"char_filter": {
"&_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
{
"text": "tom&jerry are a friend in the house, <a>, HAHA!!",
"analyzer": "my_analyzer"
}
{
"tokens": [
{
"token": "tomandjerry",
"start_offset": ,
"end_offset": ,
"type": "<ALPHANUM>",
"position":
},
{
"token": "are",
"start_offset": ,
"end_offset": ,
"type": "<ALPHANUM>",
"position":
},
{
"token": "friend",
"start_offset": ,
"end_offset": ,
"type": "<ALPHANUM>",
"position":
},
{
"token": "in",
"start_offset": ,
"end_offset": ,
"type": "<ALPHANUM>",
"position":
},
{
"token": "house",
"start_offset": ,
"end_offset": ,
"type": "<ALPHANUM>",
"position":
},
{
"token": "haha",
"start_offset": ,
"end_offset": ,
"type": "<ALPHANUM>",
"position":
}
]
}
设置使用分词自定义
PUT /my_index/_mapping/my_type
{
"properties": {
"content": {
"type": "text",
"analyzer": "my_analyzer"
}
}
}
mapping root object深入剖析
- root object
就是某个type对应的mapping json,包括了properties,metadata(_id,_source,_type),settings(analyzer),其他settings(比如include_in_all)PUT /my_index
{
"mappings": {
"my_type": {
"properties": {}
}
}
} properties
PUT /my_index/_mapping/my_type
{
"properties": {
"title": {
"type": "text"
}
}
}- _source
好处
(1)查询的时候,直接可以拿到完整的document,不需要先拿document id,再发送一次请求拿document
(2)partial update基于_source实现
(3)reindex时,直接基于_source实现,不需要从数据库(或者其他外部存储)查询数据再修改
(4)可以基于_source定制返回field
(5)debug query更容易,因为可以直接看到_source如果不需要上述好处,可以禁用_source
PUT /my_index/_mapping/my_type2
{
"_source": {"enabled": false}
} - _all
将所有field打包在一起,作为一个_all field,建立索引。没指定任何field进行搜索时,就是使用_all field在搜索。PUT /my_index/_mapping/my_type3
{
"_all": {"enabled": false}
}也可以在field级别设置include_in_all field,设置是否要将field的值包含在_all field中
PUT /my_index/_mapping/my_type4
{
"properties": {
"my_field": {
"type": "text",
"include_in_all": false
}
}
} - 标识性metadata
_index,_type,_id
定制化自己的dynamic mapping策略
dynamic参数
- true: 遇到陌生字段就进行dynamic mapping
- false: 遇到陌生字段就忽略
- strict: 遇到陌生字段,就报错
举例:
PUT my_index
{
"mappings": {
"my_type":{
"dynamic": "strict",
"properties": {
"title":{
"type": "text"
},
"address":{
"type": "object",
"dynamic":"true"
}
}
}
}
}
PUT /my_index/my_type/
{
"title": "my article",
"content": "this is my article",
"address": {
"province": "guangdong",
"city": "guangzhou"
}
} {
"error": {
"root_cause": [
{
"type": "strict_dynamic_mapping_exception",
"reason": "mapping set to strict, dynamic introduction of [content] within [my_type] is not allowed"
}
],
"type": "strict_dynamic_mapping_exception",
"reason": "mapping set to strict, dynamic introduction of [content] within [my_type] is not allowed"
},
"status":
}
PUT /my_index/my_type/
{
"title": "my article",
"address": {
"province": "guangdong",
"city": "guangzhou"
}
} GET /my_index/_mapping/my_type {
"my_index": {
"mappings": {
"my_type": {
"dynamic": "strict",
"properties": {
"address": {
"dynamic": "true",
"properties": {
"city": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above":
}
}
},
"province": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above":
}
}
}
}
},
"title": {
"type": "text"
}
}
}
}
}
}
定制dynamic mapping策略
- date_detection
elasticsearch默认会按照一定格式识别date,比如yyyy-MM-dd。但是如果某个field先过来一个2017-01-01的值,就会被自动dynamic mapping成date,后面如果再来一个"hello world"之类的值,就会报错。此时的解决方案是可以手动关闭某个type的date_detention,如果有需要,自己手动指定某个field为date类型。PUT /my_index/_mapping/my_type
{
"date_detection": false
} - dynamic template
PUT my_index
{
"mappings": {
"my_type":{
"dynamic_templates": [
{
"en":{
"match":"*_en",
"match_mapping_type": "string",
"mapping": {
"type":"string",
"analyzer":"english"
}
}
}
]
}
}
}初始化数据
PUT /my_index/my_type/
{
"title": "this is my first article"
} PUT /my_index/my_type/
{
"title_en": "this is my first article"
}无模板匹配
GET /my_index/my_type/_search
{
"query": {
"match": {
"title":"is"
}
}
}{
"took": ,
"timed_out": false,
"_shards": {
"total": ,
"successful": ,
"failed":
},
"hits": {
"total": ,
"max_score": 0.2824934,
"hits": [
{
"_index": "my_index",
"_type": "my_type",
"_id": "",
"_score": 0.2824934,
"_source": {
"title": "this is my first article"
}
}
]
}
}有模板匹配
GET /my_index/my_type/_search
{
"query": {
"match": {
"title_en":"is"
}
}
}{
"took": ,
"timed_out": false,
"_shards": {
"total": ,
"successful": ,
"failed":
},
"hits": {
"total": ,
"max_score": null,
"hits": []
}
}此时title没有匹配到任何的dynamic模板,默认就是standard分词器,不会过滤停用词,is会进入倒排索引,用is来搜索就可以搜索到。而title_en匹配到了dynamic模板,就是english分词器,会过滤停用词,is这种停用词就会被过滤掉,用is来搜索就搜索不到了。
基于scoll+bulk+索引别名实现零停机重建索引
- 数据准备
一个field的设置是不能被修改的,如果要修改一个field,那么应该重新按照新的mapping,建立一个index,然后将数据批量查询出来,重新用bulk api写入index中,批量查询的时候,建议采用scroll api,并且采用多线程并发的方式来reindex数据,每次scroll就查询指定日期的一段数据,交给一个线程即可。
一开始,依靠dynamic mapping,插入数据,但是不小心有些数据是2017-01-01这种日期格式的,所以title的这种field被自动映射为了date类型,实际上它应该是string类型。DELETE /my_index
PUT /my_index/my_type/
{
"title": "2017-01-01"
} PUT /my_index/my_type/
{
"title": "2017-01-02"
} PUT /my_index/my_type/
{
"title": "2017-01-03"
}GET /my_index/my_type/_search
{
"query": {
"match_all": {}
}
} {
"took": ,
"timed_out": false,
"_shards": {
"total": ,
"successful": ,
"failed":
},
"hits": {
"total": ,
"max_score": ,
"hits": [
{
"_index": "my_index",
"_type": "my_type",
"_id": "",
"_score": ,
"_source": {
"title": "2017-01-02"
}
},
{
"_index": "my_index",
"_type": "my_type",
"_id": "",
"_score": ,
"_source": {
"title": "2017-01-01"
}
},
{
"_index": "my_index",
"_type": "my_type",
"_id": "",
"_score": ,
"_source": {
"title": "2017-01-03"
}
}
]
}
} - 当后期向索引中加入string类型的title值的时候,就会报错
PUT /my_index/my_type/
{
"title": "my first article"
}{
"error": {
"root_cause": [
{
"type": "mapper_parsing_exception",
"reason": "failed to parse [title]"
}
],
"type": "mapper_parsing_exception",
"reason": "failed to parse [title]",
"caused_by": {
"type": "illegal_argument_exception",
"reason": "Invalid format: \"my first article\""
}
},
"status":
} - 如果此时想修改title的类型,是不可能的
PUT /my_index/_mapping/my_type
{
"properties": {
"title": {
"type": "text"
}
}
}{
"error": {
"root_cause": [
{
"type": "illegal_argument_exception",
"reason": "mapper [title] of different type, current_type [date], merged_type [text]"
}
],
"type": "illegal_argument_exception",
"reason": "mapper [title] of different type, current_type [date], merged_type [text]"
},
"status":
} - 此时,唯一的办法,就是进行reindex,也就是说,重新建立一个索引,将旧索引的数据查询出来,再导入新索引
- 如果说旧索引的名字,是old_index,新索引的名字是new_index,终端java应用,已经在使用old_index在操作了,难道还要去停止java应用,修改使用的index为new_index,才重新启动java应用吗?这个过程中,就会导致java应用停机,可用性降低
- 所以说,给java应用一个别名,这个别名是指向旧索引的,java应用先用着,java应用先用goods_index alias来操作,此时实际指向的是旧的my_index
PUT /my_index/_alias/goods_index
- 新建一个index,调整其title的类型为string
PUT my_index_new
{
"mappings": {
"my_type":{
"properties": {
"title":{
"type": "text"
}
}
}
}
} - 使用scroll api将数据批量查询出来
GET my_index/_search?scroll=1m
{
"query": {
"match_all": {}
},
"sort": [
"_doc"
],
"size":
}{
"_scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAARhWFjFMZHFMRnF4UVFxNHhnMk1waElfZ3cAAAAAAAEYWBYxTGRxTEZxeFFRcTR4ZzJNcGhJX2d3AAAAAAABGFoWMUxkcUxGcXhRUXE0eGcyTXBoSV9ndwAAAAAAARhXFjFMZHFMRnF4UVFxNHhnMk1waElfZ3cAAAAAAAEYWRYxTGRxTEZxeFFRcTR4ZzJNcGhJX2d3",
"took": ,
"timed_out": false,
"_shards": {
"total": ,
"successful": ,
"failed":
},
"hits": {
"total": ,
"max_score": null,
"hits": [
{
"_index": "my_index",
"_type": "my_type",
"_id": "",
"_score": null,
"_source": {
"title": "2017-01-02"
},
"sort": [ ]
}
]
}
} - 采用bulk api将scoll查出来的一批数据,批量写入新索引
POST _bulk
{"index":{"_index": "my_index_new", "_type": "my_type", "_id": ""}}
{"title":"2017-01-02"} - 反复循环8~9,查询一批又一批的数据出来,采取bulk api将每一批数据批量写入新索引
- 将goods_index alias切换到my_index_new上去,java应用会直接通过index别名使用新的索引中的数据,java应用程序不需要停机,零提交,高可用
POST _aliases
{
"actions": [
{
"remove": {
"index": "my_index",
"alias": "goods_index"
}
},
{
"add": {
"index": "my_index_new",
"alias": "goods_index"
}
}
]
} - 直接通过goods_index别名来查询,是否ok
GET /goods_index/my_type/_search
基于alias对client客户端透明切换index
格式:
POST /_aliases
{
"actions" : [
{ "remove" : { "index" : "test1", "alias" : "alias1" } },
{ "add" : { "index" : "test2", "alias" : "alias1" } }
]
}
Elasticsearch由浅入深(十一)索引管理的更多相关文章
- Elasticsearch中的索引管理和搜索常用命令总结
添加一个index,指定分片是3,副本是1 curl -XPUT "http://10.10.110.125:9200/test_ods" -d' { "settings ...
- ElasticSearch权威指南学习(索引管理)
创建索引 当我们需要确保索引被创建在适当数量的分片上,在索引数据之前设置好分析器和类型映射. 手动创建索引,在请求中加入所有设置和类型映射,如下所示: PUT /my_index { "se ...
- elasticsearch系列二:索引详解(快速入门、索引管理、映射详解、索引别名)
一.快速入门 1. 查看集群的健康状况 http://localhost:9200/_cat http://localhost:9200/_cat/health?v 说明:v是用来要求在结果中返回表头 ...
- elasticsearch最全详细使用教程:入门、索引管理、映射详解、索引别名、分词器、文档管理、路由、搜索详解
一.快速入门1. 查看集群的健康状况http://localhost:9200/_cat http://localhost:9200/_cat/health?v 说明:v是用来要求在结果中返回表头 状 ...
- 一文带您了解 Elasticsearch 中,如何进行索引管理(图文教程)
欢迎关注笔者的公众号: 小哈学Java, 每日推送 Java 领域干货文章,关注即免费无套路附送 100G 海量学习.面试资源哟!! 个人网站: https://www.exception.site/ ...
- MySQL索引管理
一.索引介绍 1.什么是索引 1.索引好比一本书的目录,它能让你更快的找到自己想要的内容. 2.让获取的数据更有目的性,从而提高数据库索引数据的性能. 2.索引类型介绍 1.BTREE:B+树索引 2 ...
- 第六章· MySQL索引管理及执行计划
一.索引介绍 1.什么是索引 1)索引就好比一本书的目录,它能让你更快的找到自己想要的内容. 2)让获取的数据更有目的性,从而提高数据库检索数据的性能. 2.索引类型介绍 1)BTREE:B+树索引 ...
- Elasticsearch 快照生命周期管理 (SLM) 实战指南
文章转载自:https://mp.weixin.qq.com/s/PSfgPJc4dKN2pOZd0Y02wA 1.Elasticsearch 保证高可用性的方式 Elasticsearch 保证集群 ...
- 手动刷新magento的索引管理方法
当我们网站商品很多的时候,比如有几千件,我们刷新Magento的索引管理(Index Management)经常会失败.那么后台刷新不了,我们还可以通过命令行来刷新. 使用命令行来刷新索引管理会极大降 ...
- Elasticsearch 之 数据索引
对于提供全文检索的工具来说,索引时一个关键的过程——只有通过索引操作,才能对数据进行分析存储.创建倒排索引,从而让使用者查询到相关的信息. 本篇就ES的数据索引操作相关的内容展开: 更多内容参考:El ...
随机推荐
- Java & PHP RSA 互通密钥、签名、验签、加密、解密
RSA加密算法是一种非对称加密算法.在公开密钥加密和电子商业中RSA被广泛使用.RSA是1977年由罗纳德·李维斯特(Ron Rivest).阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Le ...
- Kubernetes RBAC授权普通用户对命名空间访问权限
Kubernetes RBAC授权普通用户对命名空间访问权限 官方文档:https://www.cnblogs.com/xiangsikai/p/11413970.html kind: Role ap ...
- A Pattern Language for Parallel Application Programming
A Pattern Language for Parallel Application Programming Berna L. Massingill, Timothy G. Mattson, Bev ...
- Logstash处理数据用法示例---待完善
filter { mutate { rename => [ "message", "blog_html" ] copy => { "blo ...
- abstract,virtual,override
1.abstract 可以修饰类和方法,修饰方法时只声明不实现: 2.继承实现abstract类必须通过override实现abstract声明的方法,而virtual方法可选择override(重写 ...
- Maven环境搭配及继承
1. Maven简单介绍 Apache Maven是个项目管理和自动构建工具,基于项目对象模型(POM)的概念. 作用:完成项目的相关操作,如:编译,构建,单元测试,安装,网站生成和基于Maven部署 ...
- MySQL基础(四)(子查询与链接)
1.子查询简介 其中,所谓的“外层查询”并不是指“查找”,指的是所有SQL语句的统称:结构化查询语言(Structured Query Language),简称SQL. : 2.由比较运算符引发的子查 ...
- git报错 - remote: HTTP Basic: Access denied
十年河东,十年河西,莫欺少年穷 学无止境,精益求精 git 拉取代码报: remote: HTTP Basic: Access denied,这是因为你的GIT密码修改后,需要重新认证授权,那么怎么操 ...
- Valgrind调试
Valgrind的最初作者是Julian Seward,他于2006年由于在开发Valgrind上的工作获得了第二届Google-O'Reilly开源代码奖 摘自 Valgrind.org: Valg ...
- Lerp在X秒内插值
在X秒内插值 我们知道Mathf.Lerp函数的是用在两个值之间进行插值,用于平滑过渡. var 插值结果 = Mathf.Lerp(from,to,rate) //rate是0~1的值 Unity没 ...