前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >016.Elasticsearch文档管理操作

016.Elasticsearch文档管理操作

作者头像
CoderJed
发布2020-07-02 10:33:21
4420
发布2020-07-02 10:33:21
举报
文章被收录于专栏:Jed的技术阶梯Jed的技术阶梯

1.1 创建测试用index

代码语言:javascript
复制
curl -X PUT "node01:9200/nba"

curl -X PUT "node01:9200/nba" -H 'Content-Type:application/json' -d'
{
    "mappings": {
        "_doc": {
            "properties": {
                "jerse_no": {
                    "type": "keyword"
                },
                "name": {
                    "type": "text"
                },
                "play_year": {
                    "type": "keyword"
                },
                "position": {
                    "type": "keyword"
                },
                "team_name": {
                    "type": "text"
                },
                "country": {
                    "type": "keyword"
                }
            }
        }
    }
}
'

1.2 自动创建索引

当向一个不存在的index中添加document时,可以自动创建索引,也可以根据传入的数据自动创建mapping,ES也会自动对这些文档进行倒排索引

代码语言:javascript
复制
# 查看ES集群配置
curl -X GET "node01:9200/_cluster/settings"

{
    "persistent":{},
    "transient":{}
}

# 设置自动创建index功能
curl -X PUT "node01:9200/_cluster/settings" -H 'Content-Type:application/json' -d'
{
    "persistent": {
        "action.auto_create_index": "false"
    }
}
'

{   "acknowledged":true,
    "persistent":{
        "action":{
            "auto_create_index":"false"
        }
    },
    "transient":{}
}

当把action.auto_create_index设置成false后,就不可以向不存在的index插入数据了

1.2 添加document

代码语言:javascript
复制
# 手动指定id
curl -X PUT "node01:9200/nba/_doc/1" -H 'Content-Type:application/json' -d'
{
    "name":"哈登",
    "team_name":"火箭",
    "position":"得分后卫",
    "play_year":"10",
    "jerse_no":"13",
    "country": "美国"
}
'
# 也可以让ES自动生成id,不指定id要使用POST请求
curl -X POST "node01:9200/nba/_doc" -H 'Content-Type:application/json' -d'
{
    "name":"库里",
    "team_name":"勇士",
    "position":"控球后卫",
    "play_year":"10",
    "jerse_no":"13",
    "country": "美国"
}
'

# 可以手动指定操作类型
# 指定操作类型时,必须手动设置id
# 当不指定操作时,假如原来已经有id=2的document,那么执行以下操作就会把原来的覆盖掉
# 而指定操作为"create",那么当id=2的document已经存在时,就会报错
curl -X POST "node01:9200/nba/_doc/2?op_type=create" -H 'Content-Type:application/json' -d'
{
    "name":"姚明",
    "team_name":"火箭",
    "position":"中锋",
    "play_year":"9",
    "jerse_no":"11",
    "country": "中国"
}
'

自动设置id与手动设置id的比较:

  • 手动设置id

一般来说,从其他外部系统导入数据到es时,会采取这种方式,使用外部系统中已有数据的唯一标识,作为document的id,例如数据从MySQL导入到ES中,就可以直接使用MySQL表中自己的id

  • 自动生成id

自动生成的id,长度为20个字符,URL安全,base64编码,使用GUID算法可以保证在并行生成id时也不会发生冲突,在直接往ES中写数据的时候,可以使用这种方式

1.3 查看文档

查看单个文档

代码语言:javascript
复制
curl -X GET "node01:9200/nba/_doc/1"

{
    "_index":"nba",
    "_type":"_doc",
    "_id":"1",
    "_version":1,
    "_seq_no":0,
    "_primary_term":1,
    "found":true,
    "_source": {
        "name":"哈登",
        "team_name":"火箭",
        "position":"得分后卫",
        "play_year":"10",
        "jerse_no":"13",
        "country": "美国"
    }
}

文档元数据解析:

  • _index:此文档属于哪个index
  • _type:此文档属于哪个type
  • _id:此文档的id
  • _version:此文档的版本号,ES基于此版本进行并发控制
  • _source:此文档的数据内容

指定返回结果的字段:

代码语言:javascript
复制
curl -X GET "node01:9200/nba/_doc/1?_source=name,country"

{
    "_index":"nba",
    "_type":"_doc",
    "_id":"1",
    "_version":1,
    "_seq_no":0,
    "_primary_term":1,
    "found":true,
    "_source": {
        "name":"哈登",
        "country": "美国"
    }
}

查看多个文档

代码语言:javascript
复制
curl -X POST "node01:9200/_mget" -H 'Content-Type:application/json' -d'
{
    "docs": [
        {
            "_index": "nba",
            "_type": "_doc",
            "_id": "1"
        },
        {
            "_index": "nba",
            "_type": "_doc",
            "_id": "2"
        }
    ]
}
'

curl -X POST "node01:9200/nba/_mget" -H 'Content-Type:application/json' -d'
{
    "docs": [
        {
            "_type": "_doc",
            "_id": "1"
        },
        {
            "_type": "_doc",
            "_id": "2"
        }
    ]
}
'

curl -X POST "node01:9200/nba/_doc/_mget" -H 'Content-Type:application/json' -d'
{
    "docs": [
        {
            "_id": "1"
        },
        {
            "_id": "2"
        }
    ]
}
'

curl -X POST "node01:9200/nba/_doc/_mget" -H 'Content-Type:application/json' -d'
{
    "ids": ["1", "2"]
}
'

说明:

mget是很重要的,查询的时候,如果一次性要查询多条数据的话,那么一定要用mget,尽可能减少网络开销次数,这样可以大幅提升查询性能

1.4 修改文档

代码语言:javascript
复制
# 方法一:直接覆盖原文档
# 但是要列出所有的field,即使这个field不修改
# 否则新的文档就不包含你没有写的那个field了
# 当然,如果就是要删除这个字段,就不用写了
curl -X PUT "node01:9200/nba/_doc/1" -H 'Content-Type:application/json' -d'
{
    "name":"大胡子",
    "team_name":"火箭",
    "position":"得分后卫",
    "play_year":"9",
    "jerse_no":"13",
    "country": "美国"
}
'

# 方法二:修改指定的字段
curl -X POST "node01:9200/nba/_doc/1/_update" -H 'Content-Type:application/json' -d'
{
    "doc": {
        "name":"登哥"
    }
}
'
# ES7.x
curl -X POST "node01:9200/nba/_update/1" -H 'Content-Type:application/json' -d'
{
    "doc": {
        "name":"登哥"
    }
}
'

# 增加一个字段
curl -X POST "node01:9200/nba/_doc/1/_update" -H 'Content-Type:application/json' -d'
{
    "script": "ctx._source.age=18"
}
'
# ES7.x
curl -X POST "node01:9200/nba/_update/1" -H 'Content-Type:application/json' -d'
{
    "script": "ctx._source.age=18"
}
'

# 删除一个字段
curl -X POST "node01:9200/nba/_doc/1/_update" -H 'Content-Type:application/json' -d'
{
    "script": "ctx._source.remove(\"age\")"
}
'
# ES7.x
curl -X POST "node01:9200/nba/_update/1" -H 'Content-Type:application/json' -d'
{
    "script": "ctx._source.remove(\"age\")"
}
'

# 根据参数值,更新字段,要求文档存在并且修改的field存在
curl -X POST "node01:9200/nba/_doc/1/_update" -H 'Content-Type:application/json' -d'
{
    "script": "ctx._source.age+=params.age",
    "params": {
        "age": 4
    }
}
'
# 根据参数值,更新字段,如果文档不存在,新创建一个文档,并且将upsert中的数据插入到该文档中
curl -X POST "node01:9200/nba/_doc/3/_update" -H 'Content-Type:application/json' -d'
{
    "script": {
        "source": "ctx._source.age+=params.age",
        "params": {
            "age": 4
        }
    },
    "upsert": {
        "age": 10
    }
}
'

说明:

修改一个文档的某个字段,在ES的底层,其实也是全量替换,将原来的文档标记为delete状态,新插入一条数据,根据客户端传入的字段加上原数据的其他字段组成了一条新的文档,只不过,这些操作都在shard内部去做了,相比于让用户执行全量替换的操作,优化了网络传输开销,减少了查询和修改的时间开销,提升了性能。

1.5 删除文档

代码语言:javascript
复制
curl -X DELETE "node01:9200/nba/_doc/3"

1.6 批量增删改查

语法:

代码语言:javascript
复制
POST /_bulk
{"delete": {"_index": "index_name", "_type": "type_name", "_id": 1}}
{"create": {"_index": "index_name", "_type": "type_name", "_id": 4}}
{"doc": {"field": "value"}}
{"create": {"_index": "index_name", "_type": "type_name", "_id": 5}}
{"doc": {"field1": "value1", "field2": "value2"}}
{"update": {"_index": "index_name", "_type": "type_name", "_id": 1, "some_properties": "properties_value"}}
{"doc": {"field": "value"}}

# 例如:
POST /_bulk
{"delete": {"_index": "user", "_type": "_doc", "_id": 5}}
{"create": {"_index": "user", "_type": "_doc", "_id": 6}}
{"doc": {"uid": "1006", "uname": "Nancy"}}
{"index": {"_index": "shop", "_type": "product", "_id": 5}}
{"doc": {"name": "Gaolujie Toothpaste"}}
{"update": {"_index": "user", "_type": "_doc", "_id": 1, "retry_on_conflict": 3}}
{"doc": {"name": "Nancy"}}

bulk api对json的语法有严格的要求,每个json串不能换行,只能放一行,同时一个json串和一个json串之间,必须换行,除"delete"操作外,每个操作要两个json串,语法如下:

代码语言:javascript
复制
{"action": {"metadata"}}
{"data"}

# action包括:
delete:删除一个文档,只要1个json串就可以了
create:PUT /index/type/id/_create,强制创建
index:普通的put操作,可以是创建文档,也可以是全量替换文档
update:更新操作

任意一个操作失败,不会影响其他操作,但是在返回结果里,会告诉你哪个操作失败了及其错误信息

批量操作会将所有请求加载到内存中,一次请求过多的话,性能反而会下降,一般从5000-1W条数据开始测试,以得到一个最佳性能,同时,一般来说,将一次请求的大小在5-15MB之间

为什么批量操作对请求json字符串的要求这么严格呢?

bulk中的每个操作都可能要转发到不同的node的shard去执行,如果采用比较良好的json数组格式,允许任意的换行,整个可读性非常棒,读起来很爽,es拿到那种标准格式的json串以后,要按照下述流程去进行处理:

  • 将json数组解析为JSONArray对象,整个数据在内存中出现两份,一份数据是json文本,一份数据是JSONArray对象
  • 解析json数组里的每个json,对每个请求中的document进行路由
  • 为路由到同一个shard上的多个请求,创建一个请求数组
  • 将这个请求数组序列化
  • 将序列化后的请求数组发送到对应的节点上去

这样就耗费更多内存,造成更多的jvm gc开销,导致性能下降,而使用这种严格的json格式之后:

  • 不用解析json字符串,不用将其转换为json对象,不会出现内存中的相同数据的拷贝,直接按照换行符切割json
  • 对每两个一组的json,读取其请求信息,进行document路由
  • 直接将json发送到对应的node上去

这样,减少了内存开销,减少了解析成本,提高了性能

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.1 创建测试用index
  • 1.2 自动创建索引
  • 1.2 添加document
  • 1.3 查看文档
    • 查看单个文档
      • 查看多个文档
      • 1.4 修改文档
      • 1.5 删除文档
      • 1.6 批量增删改查
      相关产品与服务
      文件存储
      文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档