一、索引操作
- 创建索引
- 创建索引时根据需求对索引设置主分片和副分片的数量,请求类型为:put,示例代码如下:
PUT/${index_name} { "settings":{ ...... } "mappings":{ ..... } } //其中index_name:索引名称,在settings子句内部填写索引相关的设置项,如主分片和副分片的个数 //mappings子句内部填写数据结构,即数据映射 //例如 //PUT /test_index { "settings":{ "number_of_shaeds":15, //指定主分片的数量,一旦设定好不能更改主分片的数量。默认值为:5 "number_of_replicas":2 //副分片的数量 默认值为:0 } "mappings":{ "properties":{ ...... } } } //例如: { "settings":{ "number_of_shards" : 3, "number_of_replicas" : 0 }, "mappings":{ "books":{ "properties":{ "title":{"type":"text"}, "name":{"type":"text","index":false}, "publish_date":{"type":"date","index":false}, "price":{"type":"double"}, "number":{ "type":"object", "dynamic":true } } } } }
- 创建索引时根据需求对索引设置主分片和副分片的数量,请求类型为:put,示例代码如下:
- 删除索引
- ES删除索引的请求类型为:DELETE,请求代码如下:
//请求类型:DELETE,请求地址:/${index_name} //其中index_name为索引名称,执行成功后,返回信息: { "acknowledged" : true //操作成功,通知信息 }
- ES删除索引的请求类型为:DELETE,请求代码如下:
- 关闭索引
- 在有些场景中,某个索引暂时不想用了,但是又不想删除这个索引,此时我们可以将这个索引关闭,实例代码如下:
//请求类型:post,请求地址:http://[ip]:[端口号]/${index_name}/_close //如果在写入数据,报错: { "error" : { "root_cause" : [ { "type" : "index_closed_exception", //提示异常类型为索引已经关闭 "reason" : "closed", "index_uuid" : "TIYkM2N5SCKlnmCOXuJPmg", "index" : "hotel" //当前索引名称 } ], "type" : "index_closed_exception", "reason" : "closed", "index_uuid" : "TIYkM2N5SCKlnmCOXuJPmg", "index" : "hotel" }, "status" : 400 }
- 在有些场景中,某个索引暂时不想用了,但是又不想删除这个索引,此时我们可以将这个索引关闭,实例代码如下:
- 打开索引
- 打开索引,示例代码如下:
//请求类型:post,请求地址:http://[ip]:[端口号]/${index_name}/_open
- 打开索引,示例代码如下:
- 索引别名
- 索引的别名是指给一个或者多个索引定义一个另外的名称,是索引别名和索引之间可以建立某种逻辑关系。
-
比如,我们建立了1月,2月,3月的入住酒店的日志索引,假设当前日期为4月1日,我们想查询前三个月的日志信息,需要进行三遍挨个的查询,显然这样很低效,这时我们可以用索引别名,设置前三个月的索引别名为:last-three-month ,然后对last-three-month中搜索即可,如图:
- 例如:创建了三个索引分别是(es_test_01_log,es_test_02_log,es_test_03_log),并创建文档,字段(title,uuid),新建别名,代码如下:
//请求方式为:post //请求格式:http://[ip]:[端口号]/_aliases { "actions":[ { "add":{ "index":"[索引名称]", "alias":[索引别名] } }, ... ] } //示例代码如下: { "actions":[ { "add":{ "index":"es_test_01_log", "alias":"es_test" } }, { "add":{ "index":"es_test_02_log", "alias":"es_test" } }, { "add":{ "index":"es_test_03_log", "alias":"es_test" } } ] }
- 查询结果,代码如下
由上面的结果可知,使用别名es_test查询数据时,ES将请求转发给了es_test_01_log/es_test_02_log/es_test_03_log三个索引中,需要指出的是在默认情况下,当一个别名只指向一个索引时,写入数据的请求会指向这个别名,如果一个别名指向多个索引,则写入数据的请求时不可以指向这个别名,报错内容如下://请求方式:post //请求地址:http://[ip]:[端口号]/es_test[别名名称]/_search { "took": 20, "timed_out": false, "_shards": { "total": 9, "successful": 9, "skipped": 0, "failed": 0 }, "hits": { "total": 3, "max_score": 0.2876821, "hits": [ { "_index": "es_test_01_log", "_type": "books", "_id": "001", "_score": 0.2876821, "_source": { "title": "es_test_03_log", "uid": "003" } }, { "_index": "es_test_02_log", "_type": "books", "_id": "001", "_score": 0.2876821, "_source": { "title": "es_test_03_log", "uid": "003" } }, { "_index": "es_test_03_log", "_type": "books", "_id": "001", "_score": 0.2876821, "_source": { "title": "es_test_03_log", "uid": "003" } } ] } }
这种情况下需要设置目标索引"is_write_index"的属性为“true”来指定该索引可用于执行写入数据的操作,比如:写入数据的目标索引:(es_test_01_log)DSL代码如下:{ "error" : { "root_cause" : [ { //无法写入数据的报错信息 "type" : "illegal_argument_exception", "reason" : "no write index is defined for alias [last_three_month]. The write index may be explicitly disabled using is_write_index=false or the alias points to multiple indices without one being designated as a write index" } ], //无法写入数据的报错信息 "type" : "illegal_argument_exception", "reason" : "no write index is defined for alias [last_three_month]. The write index may be explicitly disabled using is_write_index=false or the alias points to multiple indices without one being designated as a write index" }, "status" : 400 //返回状态码 }
执行完上述代码,使用post方式访问访问es_test,别名会直接将请求转发给es_test_01_log,并将数据写入到ES中。//请求方式为Post //请求地址:http://[ip]:[端口号]/_aliases { "actions":[ { "add":{ "index":"es_test_01_log", "alias":"es_test", "is_write_index":true } }, { "add":{ "index":"es_test_02_log", "alias":"es_test" } }, { "add":{ "index":"es_test_03_log", "alias":"es_test" } } ] } //执行添加数据 //请求类型:POST //请求地址:http://[ip]:[端口号]/es_test[别名]/_doc //Body { "title":"es_test_04_log", "uid":"004" } //返回结果: { "_index": "es_test_01_log", "_type": "_doc", "_id": "9uqwqIQB2lfFF4CQ5LP7", "_version": 1, "result": "created", "_shards": { "total": 1, "successful": 1, "failed": 0 }, "_seq_no": 3, "_primary_term": 1 } //使用别名查询 //请求方式:GET //请求地址:http://[ip]:[端口号]/es_test[别名]/_search //Body { "query":{ "term":{ "uid":"004" } } } //返回结果 { "took": 12, "timed_out": false, "_shards": { "total": 9, "successful": 9, "skipped": 0, "failed": 0 }, "hits": { "total": 1, "max_score": 0.2876821, "hits": [ { "_index": "es_test_01_log", "_type": "books", "_id": "9uqwqIQB2lfFF4CQ5LP7", "_score": 0.2876821, "_source": { "title": "es_test_04_log", "uid": "004" } } ] } }
- 引用别名后,还可以用别名表示索引之间的替代关系。这种关系一般实在某个索引创建后,有些参数是不能更改的(如:主分片的数量),但是随着业务的发展,索引中的数据增多,既要更改索引的设置,但是又不能更改索引的名称,这时就可以用索引别名。
- 假如初期创建的索引(es_test_01_log)设置的主分片为5,别名为:es_test,随着业务不断的发展,数据量不断的增加,由于当前设置的主分片的数据为5已经满足不了当前的数据量,而主分片又不能修改,这时我们可以用别名的方式来替代,新建索引为(es_test_02_log),别名为:es_test,主分片的数据为10,并将写入是否通过别名写入数据设置为true,但客户端查询的时候直接请求别名,既保证了数据的准确性,又能够进行扩展,写入数据的时候,也请求别名即可,别名会将请求转发给es_test_02_log进行数据添加,代码如下:
//创建es_test_01_log,并写入数据,总共四条,001,002,003,004 { "title":"es_test_01_log", "uid":"001" } //创建es_test_02_log,并写入数据,总共一条 001 { "title":"es_test_02_log", "uid":"001" } //创建别名es_test { "actions":[ { "add":{ "index":"es_test_01_log", "alias":"es_test" } }, { "add":{ "index":"es_test_02_log", "alias":"es_test", "is_write_index":true } } ] } //通过别名写入数据,是写入到es_test_02_log中 { "title":"es_test_02_log", "uid":"002" } //查询结果如下: { "took": 15, "timed_out": false, "_shards": { "total": 10, "successful": 10, "skipped": 0, "failed": 0 }, "hits": { "total": 6, "max_score": 1.0, "hits": [ { "_index": "es_test_01_log", "_type": "_doc", "_id": "003", "_score": 1.0, "_source": { "title": "es_test_01_log", "uid": "003" } }, { "_index": "es_test_01_log", "_type": "_doc", "_id": "004", "_score": 1.0, "_source": { "title": "es_test_01_log", "uid": "004" } }, { "_index": "es_test_02_log", "_type": "_doc", "_id": "9-qfrYQB2lfFF4CQ1LPW", "_score": 1.0, "_source": { "title": "es_test_02_log", "uid": "002" } }, { "_index": "es_test_01_log", "_type": "_doc", "_id": "001", "_score": 1.0, "_source": { "title": "es_test_01_log", "uid": "001" } }, { "_index": "es_test_01_log", "_type": "_doc", "_id": "002", "_score": 1.0, "_source": { "title": "es_test_01_log", "uid": "002" } }, { "_index": "es_test_02_log", "_type": "_doc", "_id": "001", "_score": 1.0, "_source": { "title": "es_test_02_log", "uid": "001" } } ] } }
- 例如:创建了三个索引分别是(es_test_01_log,es_test_02_log,es_test_03_log),并创建文档,字段(title,uuid),新建别名,代码如下:
-
- 索引的别名是指给一个或者多个索引定义一个另外的名称,是索引别名和索引之间可以建立某种逻辑关系。
二、映射操作
- 简介
- 在使用数据之前,需要构建数据的组织结构,这种组织结构在关系型数据库中叫做表结构,而在ES中我们称之为映射。作为无模式搜索引擎,ES可以在数据写入时猜测数据的数据类型,自动创建映射。
- 查看映射
//请求方式:GET //请求地址:http://[IP]:[端口号]/${index_name}/_mapping //例如:查询es_test_02_log的映射,有两个字段[title,uid] //返回结果: { "es_test_02_log": { "mappings": { "_doc": { "properties": { "title": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "uid": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } } } } } }
- 扩展映射
- 映射中的字段是不可以修改的,但是可以扩展[添加];代码如下:
//请求方式 post //请求地址:http://[IP]:[端口号]/${index_name}/_mapping //例如:在es_test_02_log添加一个字段:tag,数据类型为:text { "properties": { "tag": { //字段名 "type": "object" //数据类型 } } }
- 映射中的字段是不可以修改的,但是可以扩展[添加];代码如下:
- 基本的数据类型
- keyword 数据类型
- keyword类型是不进行切分的字符串类型。这里的“不进行切分”指的是:在索引时,对keyword类型的数据不进行切分,直接构建到倒排索引;在搜索时,对该类型的查询字符串不进行切分后的部分匹配,keyword类型数据一般用于对文档的过滤,排序和聚合。
- 场景
- 描述姓名、产品类型、用户ID、URL和状态码等
- keyword类型数据一般用于比较字符串是否相等,不对数据进行部匹配,因此一般查询这种类型的数据时使用term查询,可以理解为关系型数据库中(=[等号])。
- text类型
- text类型是可进行切分的字符串类型。这里的“可切分”指的是:在索引时,可按照相应的切词算法对文本进行切分,然后构建倒排索引;在搜索时,对该类型的查询字符串按照用户的切词算法进行切分,然后对切分后的部分匹配打分。
- 对于text类型的数据,在建立索引时ES已经进行了切分并建立了倒排索引,应该使用match进行搜索。
- 数值类型
- ES支持的数值类型有long,interger,short,byte,double,float,half_float,scaled_float和unsigned_long等。各类型所表达的数值范围可参考官方文档,网址:[https://www.elastic.co/guide/en/elasticsearch/reference/current/number.html]。为了节约存储空间并提升搜索和索引的效率,在实践中应用中,在满足需求的情况下应尽可能选泽范围小的数据类型。比如年龄字段的取值范围最大值不会超过200,因此可以选择byte类型即可。数值类型的数据可用于对文档进行过滤、排序和聚合。
- 数值类型范围查询
//请求类型:GET //请求地址:http://[IP]:[端口]/${index_name}/_search //参数设置 { "query":{ "range":{ "[字段名称]":{ "gte":[最小值], "lte":[最大值] } } } } //例如: { "query":{ "range":{ "price":{ "gte":0, "lte":100 } } } } //查询结果如: { "took": 22, "timed_out": false, "_shards": { "total": 10, "successful": 10, "skipped": 0, "failed": 0 }, "hits": { "total": 1, "max_score": 1.0, "hits": [ { "_index": "es_test_04_log", "_type": "books", "_id": "001", "_score": 1.0, "_source": { "title": "生产数据", "uid": "001", "name": "赵六", "price": 100.0 } } ] } }
- 布尔类型
- 布尔类型使用boolean来定义,用于业务中的二值表示。写入或查询给类型的数据时,其值可以使用true和false或者时字符串的形式“true”和“false”。
- 注意
- 查询boolean类型的数据可以使用term或match都可以查询数据。
- 日期类型
- 日期类型为:date
- 一般使用如下形式表示日期类型数据:
- 格式化的日期字符串
- 毫秒级的长整形,表示:1970年1月1日0点到现在的毫秒数
- 秒级别的整形,表示:1970年1月1日0点到现在的秒数
- 日期类型的默认格式为strict_date_optional_time||epoch_millis。其中strict_date_optional_time的含义是严格的时间类型,支持yyyy-MM-dd、yyyyMMdd、yyyyMMddHHmmss、yyyy-MM-ddTHH:mm:ss.SSS和yyyy-MM-ddTHH:mm:ss.SSSZ等格式,epoch_millis的含义是从1970年1月1日0点到现在的毫秒数。
- 实例代码如下:
//请求方式:PUT //请求地址:http://[IP]:[端口号]/${index_name} //创建索引 { "settings":{ "number_of_shards" : 10, "number_of_replicas" : 5 }, "mappings":{ "books":{ "properties":{ "title":{"type":"text"}, "uid":{"type":"text"}, "name":{"type":"text"}, "price":{"type":"double"}, "isshow":{"type":"boolean"}, "createbytime":{"type":"date", "format":"yyyy-MM-dd HH:mm" //时间格式化模板 } } } } } //添加文档 //请求方式:post //请求地址:http://[ip]:[端口号]/${index_name}/_doc/[id]\ { "title":"测试数据", "uid":"001", "name":"王五", "price": 10.0, "isshow":false, "createbytime":"2022-11-28 13:35" } //查询结果 //请求方式:GET //请求地址:http://[ip]:[端口号]/${index_name}/_search { "took": 14, "timed_out": false, "_shards": { "total": 10, "successful": 10, "skipped": 0, "failed": 0 }, "hits": { "total": 1, "max_score": 1.0, "hits": [ { "_index": "es_test_04_log", "_type": "books", "_id": "001", "_score": 1.0, "_source": { "title": "测试数据", "uid": "001", "name": "王五", "price": 10.0, "isshow": false, "createbytime": "2022-11-28 13:35" } } ] } }
- 时间段之间的查询
//请求类型:GET //请求地址:http://[IP]:[端口]/${index_name}/_search //参数设置 { "query":{ "range":{ "[字段名称]":{ "gte":[最小值], "lte":[最大值] } } } }
- keyword 数据类型
- 复杂的数据类型
- 数组类型
- ES数组没有定义方式,其使用方式是开箱即用的,即无需事先声明,在写入时把数据用中括号[]括起来,由ES对该字段完成定义。当然,如果事先已经定义了字段类型,在写数据时以数组形式写入,ES也会将该类型转为数组,代码如下:
//添加文档 //请求方式:POST //请求地址:http://[ip]:[端口]/${index_name}/_doc/[id] { "title":"测试数据", "uid":"001", "name":"王五", "price": 10.0, "isshow":false, "createbytime":"2022-11-28 13:35", "tag":["测试","生产"] } //查询数据 //请求方式:GET //请求地址:http://[ip]:[端口号]/${index_name}/_search //查询结果如下: { "took": 14, "timed_out": false, "_shards": { "total": 10, "successful": 10, "skipped": 0, "failed": 0 }, "hits": { "total": 1, "max_score": 1.0, "hits": [ { "_index": "es_test_04_log", "_type": "books", "_id": "001", "_score": 1.0, "_source": { "title": "测试数据", "uid": "001", "name": "王五", "price": 10.0, "isshow": false, "createbytime": "2022-11-28 13:35", "tag": [ "测试", "生产" ] } } ] } }
- 数组类型的字段适用于元素类型的搜索方式,也就是说,数组元素适用什么搜索,数组字段就适用于什么搜索。 如果数组类型用的keyword,那就用term查询,如果数组类型为text,那就是用match查询,代码如下:
//字段类型为:keyword { "query":{ "term":{ "[字段名称]":{ "value":"[值]" } } } } //字段类型为:text { "query":{ "match":{ "[字段名称]":{ "value":"[值]" } } } }
- ES数组没有定义方式,其使用方式是开箱即用的,即无需事先声明,在写入时把数据用中括号[]括起来,由ES对该字段完成定义。当然,如果事先已经定义了字段类型,在写数据时以数组形式写入,ES也会将该类型转为数组,代码如下:
- 对象类型
- 在实际业务中,一个文档需要包含其他内部对象。和数组类型一样,对象类型也不用事先定义,在写入文档的时候ES会自动识别并转换为对象类型,对象的内部可以包含多个对象,代码如下:
//写入文档 //请求方式:post //请求地址:http://[ip]:[端口号]/${index_name}/_doc/[id] { "title":"测试数据", "uid":"001", "name":"王五", "price": 10.0, "isshow":false, "createbytime":"2022-11-28 13:35", "tag":["测试","生产"], "comment_info":{ "properties":{ "favourable_comment":123, "negative_comment":456 } } } //返回结果 //请求方式:GET //请求地址:http://[ip]:[端口号]/${index_name}/_search { "took": 13, "timed_out": false, "_shards": { "total": 5, "successful": 5, "skipped": 0, "failed": 0 }, "hits": { "total": 1, "max_score": 1.0, "hits": [ { "_index": "es_test_04_log", "_type": "_doc", "_id": "001", "_score": 1.0, "_source": { "title": "测试数据", "uid": "001", "name": "王五", "price": 10.0, "isshow": false, "createbytime": "2022-11-28 13:35", "tag": [ "测试", "生产" ], "comment_info": { "properties": { "favourable_comment": 123, "negative_comment": 456 } } } } ] } } //查看索引的映射条件 //请求方式:GET //请求地址:http://[ip]:[端口号]/${index_name}/_mapping { "es_test_04_log": { "mappings": { "_doc": { "properties": { "comment_info": { "properties": { "properties": { "properties": { "favourable_comment": { "type": "long" }, "negative_comment": { "type": "long" } } } } }, "createbytime": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "isshow": { "type": "boolean" }, "name": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "price": { "type": "float" }, "tag": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "title": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "uid": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } } } } } }
- 对象中属性数据查询
//以上面添加的数据为准 //请求方式:GET //请求地址:http://[ip]:[端口号]/${index_name}/_search { "query":{ "range":{ "comment_info.properties.favourable_comment":{ "gte":100, "lte":200 } } } } //查询结果如下: { "took": 19, "timed_out": false, "_shards": { "total": 5, "successful": 5, "skipped": 0, "failed": 0 }, "hits": { "total": 1, "max_score": 1.0, "hits": [ { "_index": "es_test_04_log", "_type": "_doc", "_id": "001", "_score": 1.0, "_source": { "title": "测试数据", "uid": "001", "name": "王五", "price": 10.0, "isshow": false, "createbytime": "2022-11-28 13:35", "tag": [ "测试", "生产" ], "comment_info": { "properties": { "favourable_comment": 123, "negative_comment": 456 } } } } ] } }
- 在实际业务中,一个文档需要包含其他内部对象。和数组类型一样,对象类型也不用事先定义,在写入文档的时候ES会自动识别并转换为对象类型,对象的内部可以包含多个对象,代码如下:
- 地理类型
- 用户需要根据某个地理位置来搜所商店、酒店等,此时可以把酒店的经纬度数设置为地理的数据类型。该类型的定义需要在mapping中指定目标字段的数据类型为geo_point类型,代码如下:
//创建索引 //请求方式:put //请求地址:http://[ip]:[端口号]/${index_name} { "settings":{ "number_of_shards" : 10, "number_of_replicas" : 5 }, "mappings":{ "books":{ "properties":{ "title":{"type":"text"}, "uid":{"type":"text"}, "name":{"type":"text"}, "price":{"type":"double"}, "isshow":{"type":"boolean"}, "createbytime":{"type":"date", "format":"yyyy-MM-dd HH:mm" }, "tag":{"type":"keyword"}, "location":{"type":"geo_point"} } } } } //添加文档 //请求方式:Post //请求地址:http://[ip]:[端口号]/${index_name}/_doc/[id] //lat:维度 lon:经度 { "title":"测试数据", "uid":"001", "name":"王五", "price": 10.0, "isshow":false, "createbytime":"2022-11-28 13:35", "tag":["测试","生产"], "comment_info":{ "properties":{ "favourable_comment":123, "negative_comment":456 }, "location":{ "lat":40.012134, "lon":116.497553 } } }
- 用户需要根据某个地理位置来搜所商店、酒店等,此时可以把酒店的经纬度数设置为地理的数据类型。该类型的定义需要在mapping中指定目标字段的数据类型为geo_point类型,代码如下:
- 数组类型
- 动态映射
- 当字段没有定义时,ES会根据写入文档的数据自定义该字段的类型,这种机制叫做动态映射,在一般情况下,如果使用基本类型数据,最好先把数据类型定义好,因为ES的动态映射生成的字段类型可能会与用户预期有差别。
- 多字段
- 针对同一个字段,有时会需要不同的数据类型,这通常表现在为了不同的目的以不同的方式索引相同的字段。例如:在订单系统中,既希望能够按照用户姓名进行搜索,又可以按照姓氏进行排列,可以在mapping定义中将姓名字段先后定义为text类型和keyword类型,其中keyword类型的字段叫做子字段,这样ES在建立索引时会将姓名字段建立两份索引,既是text类型又是keyword类型,创建多字段索引代码如下:
//使用多字段创建索引 //请求方式:PUT //请求地址:http://[ip]:[端口号]/${index_name} //基本语法 使用fields 区分 { "settings":{ "number_of_shards" : 10, "number_of_replicas" : 5 }, "mappings":{ "books":{ "properties":{ "title":{"type":"text"}, "uid":{"type":"text"}, "username":{"type":"text", "fields":{"username_keyword":{ "type":"keyword" } } } } } } } //根据子字段进行排序 //请求方式:GET //请求地址:http://[ip]:[端口号]/_search //请求内容 { "query":{ "match":{ "username":"aaaa" // } }, "sort":{ "username.username_keyword":"desc" //子字段名称 } }
- 针对同一个字段,有时会需要不同的数据类型,这通常表现在为了不同的目的以不同的方式索引相同的字段。例如:在订单系统中,既希望能够按照用户姓名进行搜索,又可以按照姓氏进行排列,可以在mapping定义中将姓名字段先后定义为text类型和keyword类型,其中keyword类型的字段叫做子字段,这样ES在建立索引时会将姓名字段建立两份索引,既是text类型又是keyword类型,创建多字段索引代码如下:
三、文档操作
- 单条写入文档
- 条件
- 请求方式
- post
- 请求地址
- http://[ip]:[端口号]/${index_name}/_doc/[id]
- 请求代码
{ "id":1, "username":"小明", "sex":"男", "old":12 }
- 请求方式
- 条件
- 批量写入文档
- 请求体的第一行表示写入的文档对应的元数据,其中index_name表示写入的目标索引,第2行表示的数据体,第3行表示写入的第二条文档对应的元数据,第4行表示的数据体;
- 条件
- 请求方式
- post
- 请求地址
- http://[ip]:[端口号]/_bulk
- 请求代码
{"index":{"_index":"${index_name}"}} //指定批量写入的索引 {…} //设定写入的文档内容 {"index":{"_index":"${index_name}"}} {…} //设定写入的文档内容
- 在ES单机环境下登录服务器,然后执行curl命令将上述两个文档批量写入hotel索引中:
其中,bulk_doc.json是文件名称,文件内容如下:curl -s –XPOST '127.0.0.1:9200/_bulk?preety' --data-binary "@bulk_doc.json"
{"index":{"_index":"hotel","_id":"001"}} //指定批量请求的索引 {"title": "文雅酒店","city": "北京","price": 556.00} //写入的数据,指定文档_id {"index":{"_index":"hotel","_id":"002"}} //指定批量请求的索引 //写入的数据,指定文档_id {"title": "嘉怡假日酒店","city": "北京","price": 337.00}
- 在ES单机环境下登录服务器,然后执行curl命令将上述两个文档批量写入hotel索引中:
- 请求方式
- 更新单条文档
- 条件
- 请求方式
- POST
- 请求地址
- http://[ip]:[端口号]/${index_name}/_update/[id号]
- 请求代码
{ "doc":{ "[字段]":"[值]", ...... } }
- 除了Update的功能外,ES还提供了Upsert。Upsert既是Update和insert的合体字,表示更新/插入数据。如果目标文档存在,表示更新数据,否则执行插入数据,代码如下:
{ "doc":{ "title": "好再来酒店", "city": "北京", "price": 659.45 }, "upsert":{ "title": "好再来酒店", "city": "北京", "price": 659.45 } }
- 请求方式
- 条件
- 批量更新文档
- 批量更新文档和批量写入文档相似。
- 条件
- 请求方式
- pot
- 请求地址
- http://[ip]:[端口号]/_bulk
- 请求代码
{"update":{"_index":"${index_name}",”_id”:”${_id}”}} {“doc”:{ …}#JSON数据} //设定更新的文档内容 //指定批量更新的索引和文档_id {"update":{"_index":"${index_name}",”_id”:”${_id}”}} {“doc”:{ …}#JSON数据} //设定更新的文档内容
- 批量更新与批量写入不同的是更新文档必须是在元数据汇中填写更新文档的_id。
- 请求方式
- 根据条件更新文档
- 在索引数据的更新操作中,有些场景要根据不同的条件同时更新多条数据,为了满足这一条件,ES为用户提供了_update_by_query功能。
- 条件
- 请求方式
- post
- 请求地址
- http://[ip]:[端口号]/${index_name}/_update_by_query
- 请求代码
{ "query":{ //条件更新的查询条件 }, "script":{ //条件更新的具体更新脚本代码 } } //例如: { "query":{ "term":{ "city":"北" } }, "script":{ "source": "ctx._source['city']='北京顺义'" } } //查询是否更新数据 { "took": 17, "timed_out": false, "_shards": { "total": 10, "successful": 10, "skipped": 0, "failed": 0 }, "hits": { "total": 1, "max_score": 0.2876821, "hits": [ { "_index": "es_test_04_log", "_type": "books", "_id": "003", "_score": 0.2876821, "_source": { "city": "北京顺义", "title": "中国" } } ] } }
- 请求方式
- 删除单条文档
- 条件
- 请求方式
- delete
- 请求地址
- http://[ip]:[端口号]/ i n d e x n a m e / d o c / {index_name}/_doc/ indexname/doc/{_id}
- 请求代码
- 在postman执行即可。
- 请求方式
- 条件
- 批量删除文档
- 与批量写入和更新不同的是批量删除文档不需要提供json数据。
- 条件
- 请求方式
- post
- 请求地址
- http://[ip]:[端口号]/_bulk
- 请求代码
{"delete":{"_index":"[索引名称]","_id":"[id号]"}} //示例代码如下: {"delete":{"_index":"hotel","_id":"001"}} //批量删除文档,指定文档_id为“001” {" delete ":{"_index":"hotel","_id":"002"}} //批量删除文档,指定文档_id为“002”
- 请求方式
- 根据条件删除文档
- 请求方式
- Post
- 请求地址
- http://[ip]:[端口号]/${index_name}/_delete_by_query
- 请求代码
{ "query":{ ..... } } //实例代码如下: { "query":{ "term":{ "city":{ "value":"北" } } } }
- 请求方式