• Elasticsearch索引操作


    索引操作

    创建索引

    es创建索引的请求方式如下:

    https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html

    PUT /<index>
    • 请求的方法用PUT。
    • /后面直接跟索引的名称即可。
    • 索引的设置和字段都放在Body中。

    比如我们创建一个名字叫组织机构的索引,这个索引只有两个字段,一个id,一个name。并且这个索引设置为2个分片,2个副本。

    我们使用Postman发送请求,如下:

    http://localhost:9200/orgnization

    请求的方法选择PUT。然后在请求体(Body)中,写上索引的字段名称,索引的分片数和副本数,如下:

    {
        "settings":{
            "number_of_shards":2,
            "number_of_replicas":2
        },
        "mappings":{
            "properties":{
                "id":{
                    "type":"long"
                },
                "name":{
                    "type":"text"
                }
            }
        }
    }

    我们观察一下,请求体中分为两个部分:settings和mappings。在settings中,我们设置了分片数和副本数。

    • number_of_shards:分片的数量;
    • number_of_replicas:副本的数量;

    在mappings中,我们设置索引的字段,在这里,我们只设置了id和name,id的映射类型是long,name的映射类型是text。

    请求体写完后,我们点击发送,es返回的结果如下:

    {
        "acknowledged": true,
        "shards_acknowledged": true,
        "index": "orgnization"
    }

    说明索引创建成功,索引的名字正是我们在请求中设置的orgnization。

    然后,我们通过elasticsearch-head插件观察一下刚才创建的索引

    我们可以看到索引orgnization已经创建好了,它有2个分片,分别是0和1,并且每个分片都是两个副本。如果我们仔细观察这个图,可以看出node-chun节点中的0分片,和node-yao节点中的1分片,它们的边框是加粗的,这说明它们是主节点,而边框没有加粗的节点是从节点,也就是我们说的副本节点。

    查看索引

    如果我们要查看一个索引的设置,可以通过如下请求方式: 

    GET /<index>

    在我们的例子中,查看orgnization索引的设置,我们在Postman中发送如下的请求:

    {
        "orgnization": {
            "aliases": {},
            "mappings": {
                "properties": {
                    "id": {
                        "type": "long"
                    },
                    "name": {
                        "type": "text"
                    }
                }
            },
            "settings": {
                "index": {
                    "routing": {
                        "allocation": {
                            "include": {
                                "_tier_preference": "data_content"
                            }
                        }
                    },
                    "number_of_shards": "2",
                    "provided_name": "orgnization",
                    "creation_date": "1636182188268",
                    "number_of_replicas": "2",
                    "uuid": "93U8-D3FSf2ZsVveV6uPUw",
                    "version": {
                        "created": "7100299"
                    }
                }
            }
        }
    }

    我们可以看到索引的具体设置,比如:mapping的设置,分片和副本的设置。这些和我们创建索引时候的设置是一样的。

    修改索引

    索引一旦创建,我们是无法修改里边的内容的,不如说修改索引字段的名称。但是我们是可以向索引中添加其他字段的,添加字段的方式如下:

    PUT /<index>/_mapping

    然后在我们的请求体中,写好新添加的字段。比如,在我们的例子当中,新添加一个type字段,它的类型我们定义为long,请求如下:

    http://localhost:9200/orgnization/_mapping

    请求类型要改为PUT,请求体如下:

    {
      "properties": {
        "type": {
          "type": "long"
        }
      }
    }

    添加索引字段成功,我们再使用GET查看一下索引,如图:

    {
        "orgnization": {
            "aliases": {},
            "mappings": {
                "properties": {
                    "id": {
                        "type": "long"
                    },
                    "name": {
                        "type": "text"
                    },
                    "type": {
                        "type": "long"
                    }
                }
            },
            "settings": {
                "index": {
                    "routing": {
                        "allocation": {
                            "include": {
                                "_tier_preference": "data_content"
                            }
                        }
                    },
                    "number_of_shards": "2",
                    "provided_name": "orgnization",
                    "creation_date": "1636182188268",
                    "number_of_replicas": "2",
                    "uuid": "93U8-D3FSf2ZsVveV6uPUw",
                    "version": {
                        "created": "7100299"
                    }
                }
            }
        }
    }

    我们可以成功的查询到新添加的索引字段了。

    删除索引

    如果我们要删除一个索引,请求方式如下:

    DELETE /<index>

    假如我们要删除刚才创建的orgnization索引,我们只要把请求的方法改成DELETE,然后访问我们索引就可以

    http://localhost:9200/orgnization

    关闭索引

    如果索引被关闭,那么关于这个索引的所有读写操作都会被阻断。索引的关闭也很简单,请求方式如下:

    POST /<index>/_close

    在我们的例子中,如果要关闭索引,将请求方法改成POST,然后发送如下请求:

    http://localhost:9200/orgnization/_close

    打开索引

    与关闭索引相对应的是打开索引,请求方式如下:

    POST /<index>/_open

    在我们的例子中,如果要打开索引,将请求方法改成POST,然后发送如下请求:

    http://localhost:9200/orgnization/_open

    冻结索引

    冻结索引和关闭索引类似,关闭索引是既不能读,也不能写。而冻结索引是可以读,但是不能写。冻结索引的请求方式如下:

    POST /<index>/_freeze

    对应我们的例子当中:

    http://localhost:9200/orgnization/_freeze

    解冻索引

    与冻结索引对应的是解冻索引,方式如下:

    POST /<index>/_unfreeze

    对应我们的例子:

    http://localhost:9200/orgnization/_unfreeze

    Setting配置

    setting为ES索引的配置属性,索引的配置项按是否可以更改分静态(static)属性与动态配置。

    静态配置即索引创建后不能修改,静态配置只能在创建索引时或者在状态为 closed index的索引(闭合的索引)上设置。

    索引静态配置

    index.number_of_shards 主分片数,默认为5。只能在创建索引时设置,不能修改。

    index.shard.check_on_startup 是否在索引打开前检查分片是否损坏,当检查到分片损坏将禁止分片被打开。可选值:false:不检测;checksum:只检查物理结构;true:检查物理和逻辑损坏,相对比较耗CPU;fix:类同与false,7.0版本后将废弃。默认值:false。

    index.codec 数据存储的压缩算法,默认算法为LZ4,也可以设置成best_compression,best_compression压缩比较好,但存储性能比LZ4差。

    index.routing_partition_size 路由分区数,默认为 1,只能在索引创建时设置。此值必须小于index.number_of_shards,如果设置了该参数,如果设置了该参数,其路由算法为: (hash(_routing) + hash(_id) % index.routing_parttion_size ) % number_of_shards。如果该值不设置,则路由算法为 hash(_routing) % number_of_shardings,_routing默认值为_id。

    索引动态配置

    index.refresh_interval 执行刷新操作的频率,这使得索引的最近更改可以被搜索。默认为 1s。可以设置为 -1 以禁用刷新。

    index.max_result_window 用于索引搜索的 from+size 的最大值。默认为 10000。

    index.max_docvalue_fields_search 一次查询最多包含开启doc_values字段的个数,默认为100。

    index.number_of_replicas 每个主分片的副本数,默认为 1,该值必须大于等于0

    index.auto_expand_replicas 基于可用节点的数量自动分配副本数量,默认为 false(即禁用此功能)

    index.blocks.read_only 设置为 true 使索引和索引元数据为只读,false 为允许写入和元数据更改。

    index.max_rescore_window 在搜索此索引中 rescore 的 window_size 最大值

    index.blocks.read_only_allow_delete 与index.blocks.read_only基本类似,唯一的区别是允许删除动作。

    index.blocks.write 设置为 true 可禁用对索引的写入操作。

    index.blocks.read 设置为 true 可禁用对索引的读取操作

    index.blocks.metadata 设置为 true 可禁用索引元数据的读取和写入。

    index.max_refresh_listeners 索引的每个分片上可用的最大刷新侦听器数。

    对于已存在的索引,我们想要修改它的动态配置,可以使用_settings方法。

    PUT  /test_setting/_settings
    {
        "number_of_replicas": "0"              
    }

    mapping配置

    通常索引的 Mapping 结构可以在创建索引时由 ElasticSearch 帮我们自动构建,字段类型由 ElasticSearch 自动推断,但这样做有一些问题,比如字段类型推断不准确,默认所有字段都会构建倒排索引等,自定义Mapping就可以解决上述这些问题。

    我们创建了索引,在创建索引的时候,我们指定了mapping属性,mapping属性中规定索引中有哪些字段,字段的类型是什么。在mapping中,我们可以定义如下内容:

    • 类型为String的字段,将会被全文索引;
    • 其他的字段类型包括:数字、日期和geo(地理坐标);
    • 日期类型的格式;
    • 动态添加字段的映射规则;

    字段的可用类型如下:

    • 简单的类型,比如:text(分词),keyword(不分词),date,long,double,boolean,ip。我们可以看到,类型当中没有String,字符串的类型是text,所有text类型的字段都会被全文索引。数字类型有两个,long(长整型)和double(浮点型)。
    • JSON的层级类型:Object(对象)和Nested(数组对象)。Object类型时,该字段可以存储一个JSON对象;Nested类型时,该字段可以存储一个数组对象。
    • 复杂的类型:包括 geo_point、geo_shape和completion。

    索引的创建需要配置mapping与setting两部分。基本格式:

    {
        "mappings":{
    		"_all":{
    			"enabled":false  #默认情况,ElasticSarch自动使用_all所有的文档的域都会被加到_all中进行索引。可以使用"_all" : {"enabled":false} 开关禁用它。如果某个域不希望被加到_all中,可以使用"include_in_all":false关闭
    		},
    		"properties":{
    			"uuid":{
    				"type":"text",
    				"copy_to":"_search_all", #对应_search_all字段,可以对其进行全文检索
    				"fields":{
    					"keyword":{
    						"type":"keyword",  
    						"ignore_above":150  #ignore_above 默认值是256,当字段文本的长度大于指定值时,不做倒排索引。
    					}
    				}
    			},
    			"name":{
    				"type":"text",
    				"copy_to":"_search_all",
    				"analyzer":"ik_max_word",  # ik_max_word 插件会最细粒度分词
    				"search_analyzer":"ik_smart",  # ik_smart 粗粒度分词
    				"fields":{
    					"keyword":{
    						"type":"keyword",
    						"ignore_above":150
    					}
    				}
    			},
    			"dt_from_explode_time":{
    				"type":"date",
    				"copy_to":"_search_all",
    				"format":"strict_date_optional_time||epoch_millis"
    			},
    			"_search_all":{
    				"type":"text"
    			}
    		},
    		"date_detection":false,  #关闭日期自动检测,如果开启,会对于设置为日期格式的字段进行判断
    		"dynamic_templates":[   #用于自定义在动态添加field的时候自动给field设置的数据类型
    			{
    				"strings":{
    					"match_mapping_type":"string",
    					"mapping":{
    						"type":"text",
    						"copy_to":"_search_all",
    						"fields":{
    							"keyword":{
    								"type":"keyword",
    								"ignore_above":150
    							}
    						}
    					}
    				}
    			}
    		]
            
        },
        "settings":{
            "index":{
                "number_of_shards":6, #分片数量
                "number_of_replicas":1  #副本数量
            }
        }
    }

    常用数据类型

    text、keyword、number、array、range、boolean、date、geo_point、ip、nested、object。

    • text:默认会进行分词,支持模糊查询(5.x之后版本string类型已废弃,请大家使用text)。 
    • keyword:不进行分词,默认开启doc_values来加速聚合排序操作,占用了大量磁盘io 如非必须可以禁用doc_values。
    • number:如果只有过滤场景 用不到range查询的话,使用keyword性能更佳,另外数字类型的doc_values比字符串更容易压缩。
    • range:对数据的范围进行索引,目前支持 number range、date range 、ip range。
    • array:es不需要显示定义数组类型,只需要在插入数据时用’[]‘表示即可。[]中的元素类型需保持一致。
    • boolean: 只接受true、false,也可以是字符串类型的“true”、“false”。
    • date:支持毫秒、根据指定的format解析对应的日期格式,内部以long类型存储。
    • geo_point:存储经纬度数据对。
    • ip:将ip数据存储在这种数据类型中,方便后期对ip字段的模糊与范围查询。
    • ested:嵌套类型,一种特殊的object类型,存储object数组,可检索内部子项。
    • object:嵌套类型,不支持数组。
    {
      "mappings": {
        "properties": {
          "price": {
            "type": "long"
          },
          "color": {
            "type": "keyword"
          },
          "brand": {
            "type": "keyword"
          },
          "sold_date": {
            "type": "date", // 使用date类型时要指定format,否则在使用range查询+时间表达式now/d等时,会特别坑爹
            "format":"yyyyMMdd"
          }
        }
      }
    }

    其他参数:

    "field": {  
    	 "type":  "text", //文本类型  ,指定类型
       
    	 "index": "false"// ,设置成false,字段将不会被索引  
    	 
    	 "analyzer":"ik"//指定分词器  
    	 
    	 "boost":1.23//字段级别的分数加权  
    	 
    	 "doc_values":false//对not_analyzed字段,默认都是开启,analyzed字段不能使用,对排序和聚合能提升较大性能,节约内存,如果您确定不需要对字段进行排序或聚合,或者从script访问字段值,则可以禁用doc值以节省磁盘空间:
    	 
    	 "fielddata":{"loading" : "eager" }//Elasticsearch 加载内存 fielddata 的默认行为是 延迟 加载 。 当 Elasticsearch 第一次查询某个字段时,它将会完整加载这个字段所有 Segment 中的倒排索引到内存中,以便于以后的查询能够获取更好的性能。
    	 
    	 "fields":{"keyword": {"type": "keyword","ignore_above": 256}} //可以对一个字段提供多种索引模式,同一个字段的值,一个分词,一个不分词  
    	 
    	 "ignore_above":100 //超过100个字符的文本,将会被忽略,不被索引
    	   
    	 "include_in_all":ture//设置是否此字段包含在_all字段中,默认是true,除非index设置成no选项  
    	 
    	 "index_options":"docs"//4个可选参数docs(索引文档号) ,freqs(文档号+词频),positions(文档号+词频+位置,通常用来距离查询),offsets(文档号+词频+位置+偏移量,通常被使用在高亮字段)分词字段默认是position,其他的默认是docs  
    	 
    	 "norms":{"enable":true,"loading":"lazy"}//分词字段默认配置,不分词字段:默认{"enable":false},存储长度因子和索引时boost,建议对需要参与评分字段使用 ,会额外增加内存消耗量  
    	 
    	 "null_value":"NULL"//设置一些缺失字段的初始化值,只有string可以使用,分词字段的null值也会被分词  
    	 
    	 "position_increament_gap":0//影响距离查询或近似查询,可以设置在多值字段的数据上火分词字段上,查询时可指定slop间隔,默认值是100  
    	 
    	 "store":false//是否单独设置此字段的是否存储而从_source字段中分离,默认是false,只能搜索,不能获取值  
    	 
    	 "search_analyzer":"ik"//设置搜索时的分词器,默认跟ananlyzer是一致的,比如index时用standard+ngram,搜索时用standard用来完成自动提示功能  
    	 
    	 "similarity":"BM25"//默认是TF/IDF算法,指定一个字段评分策略,仅仅对字符串型和分词类型有效  
    	 
    	 "term_vector":"no"//默认不存储向量信息,支持参数yes(term存储),with_positions(term+位置),with_offsets(term+偏移量),with_positions_offsets(term+位置+偏移量) 对快速高亮fast vector highlighter能提升性能,但开启又会加大索引体积,不适合大数据量用  
       }

    常用的有: 

    • type:field的类型。
    • index:该field是否会被索引。
    • analyzer:指定的分词器。
    • doc_values:开启后对聚合入分组或排序有增益,默认开启。

    mapping之date date_nanos

    JSON没有date数据类型,但我们可以把以下类型的数据作为日期时间存入ES。

    在ES的内部,这些数据都是按照毫秒数(长整型)存储的,只是它们展现形式有如下多种。 

    类型说明
    字符串 日期格式的字符串,如"2015-01-01"或"2015/01/01 12:10:30"
    长整型 从开始纪元(1970-01-01 00:00:00 UTC)开始的毫秒数
    整型 从开始纪元(1970-01-01 00:00:00 UTC)开始的秒数

    上面的UTC(Universal Time Coordinated) 叫做世界统一时间,中国大陆和 UTC 的时差是 + 8 ,也就是 UTC+8。在ES内部,时间以毫秒数的UTC存储。

    1、日期格式

    date的格式可以被指定的,如果没有特殊指定,默认格式是"strict_date_optional_time||epoch_millis"

    这段话可以理解为格式为strict_date_optional_time或者epoch_millis

    (1)什么是epoch_millis?

    epoch_millis就是从开始纪元(1970-01-01 00:00:00 UTC)开始的毫秒数-长整型。

    如下图,2020/8/31 14:57:56是我们常用的日期格式,它距离1970-01-01 00:00:00 有 1598857076000豪秒。所以可以用长整型1598857076000表示2020/8/31 14:57:56。

    (2)什么是strict_date_optional_time?

    strict_date_optional_time是date_optional_time的严格级别,这个严格指的是年份、月份、天必须分别以4位、2位、2位表示,不足两位的话第一位需用0补齐。

    常见的格式有如下:

    • yyyy
    • yyyyMM
    • yyyyMMdd
    • yyyyMMddHHmmss
    • yyyy-MM
    • yyyy-MM-dd
    • yyyy-MM-ddTHH:mm:ss
    • yyyy-MM-ddTHH:mm:ss.SSS
    • yyyy-MM-ddTHH:mm:ss.SSSZ

    工作常见到是"yyyy-MM-dd HH:mm:ss",但是ES是不支持这格式的,需要在dd后面加个T,这个是固定格式。上面最后一个里大写的"Z"表示时区。

    你就是想用yyyy-MM-dd HH:mm:ss?

    date类型,还支持一个参数format,它让我们可以自己定制化日期格式。

    比如format配置了“格式A||格式B||格式C”,插入一个值后,会从左往右匹配,直到有一个格式匹配上。

     
    {
        "mappings":{
            "properties":{
                "birthday":{
                    "type":"date",
                    "format":"yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
                }
            }
        }
    }

    (3)date_nanos类型,支持纳秒

    date类型支持到毫秒,如果特殊情况下用到纳秒得用date_nanos这个类型。

    为索引自定义Mapping

    语法结构:

    {
        "mappings": {
            "properties": {
                "age": {
                    "type": "integer"
                },
                "email": {
                    "type": "keyword"
                },
                "name": {
                    "type": "text"
                }
            }
        }
    }

    PUT http://localhost:9200/users。请求的方法我们要使用PUT,路径是我们的索引名称,请求体当中是我们为索引添加的字段和字段的类型。

    最佳实践

    我们可以完全参考手册编写 Mapping ,但不建议这样做,容易出错,调试也麻烦,可以通过创建一个测试索引并插入测试文档,然后查看ElasticSearch为这个索引自动创建的Mapping,基于这个Mapping进行修改来构建我们自己的 Mapping。

    在存在的映射中添加字段

    正如上面所示,我们在一个索引中添加了字段,但是现在我们要补充额外的字段,这时,我们要怎么做呢?

    PUT /users/_mapping
    {
      "properties": {
        "employee-id": {
          "type": "keyword",
          "index": false
        }
      }
    }

    我们使用PUT方法,后面跟随我们的索引名称,再接上_mapping,请求体中是我们新添加的映射字段,我们指定了字段的类型为keyword,index索引为false,说明这个字段只用于存储,不会用于搜索,搜索这个字段是搜索不到的。

    我们在更新字段时候,是不能修改字段的类型的。如果我们要修改字段的类型,最好是新建一个新的字段,指定正确的类型,然后再更新索引,以后我们只需要查询这个新增的字段就可以了。

    查看索引中的字段映射

    如果我们要查看已知索引的字段映射,可以向ES发送如下的请求:

    GET /users/_mapping

    请求的方法是GET,请求的路径是我们索引的名称my-index,再加上一个_mapping,得到的返回结果如下:

    返回的结果中,我们可以看到索引的名称users,还有我们添加的字段,也包括后续补充的employee-id字段。  

    修改mapping中的字段类型

    mapping中字段类型一旦设定后禁止直接修改。因为lucene实现的倒排索引生成后不允许修改,除非重建索引映射,然后做reindex操作。

    以上面例子的索引orgnization为例。

    (1)创建一个备份索引orgnization_bak

    {
        "settings":{
            "number_of_shards":2,
            "number_of_replicas":2
        },
        "mappings":{
            "properties":{
                "id":{
                    "type":"long"
                },
                "name":{
                    "type":"text"
                }
            }
        }
    }

    (2) reindex操作 

    POST http://localhost:9200/_reindex

    请求体:

    {
      "source": {"index":"旧索引"},
      "dest": {"index":"备份索引"}
    }

    其中旧索引就是orgnization,备份索引是orgnization_bak。

    (3)删除旧索引orgnization

    (4)创建新索引orgnization,重新指定字段类型

    {
        "settings":{
            "number_of_shards":2,
            "number_of_replicas":2
        },
        "mappings":{
            "properties":{
                "id":{
                    "type":"long"
                },
                "name":{
                    "type":"keyword"
                }
            }
        }
    }

    (5)再reindex操作 

    POST http://localhost:9200/_reindex

    请求体为:

    {
      "source": {"index":"备份索引"},
      "dest": {"index":"新索引"}
    }

    此时的备份索引是orgnization_bak,新索引就是我们刚刚创建的orgnization。

  • 相关阅读:
    Android Studio 解决unspecified on project app resolves to an APK archive which is not supported
    IOS 一句代码搞定启动引导页
    iOS—最全的真机测试教程
    Hue的三大特点、三大功能和架构
    CentOS和Ubuntu系统下安装vsftp(助推大数据部署搭建)
    Starting vsftpd for vsftpd: [FAILED]问题的解决
    大数据搭建各个子项目时配置文件技巧(适合CentOS和Ubuntu系统)(博主推荐)
    CentOS6.5下Cloudera安装搭建部署大数据集群(图文分五大步详解)(博主强烈推荐)
    Hue的全局配置文件hue.ini(图文详解)
    Cloudera Hue是什么?
  • 原文地址:https://www.cnblogs.com/hanease/p/16172923.html
Copyright © 2020-2023  润新知