ElasticSearch文档操作详解

文档的介绍

作为Elasticsearch的基本存储单元,文档是指存储在Elasticsearch索引中的JSON对象。

文档的基本操作

新增文档

使用POST请求新增文档
当不指定文档ID时,可以使用POST请求来新增文档,Elasticsearch会自动生成一个唯一的ID。语法如下:

POST /employee/_doc
{
    "name":"李四",
    "sex":1,
    "age":25,
    "address":"广州天河公园",
    "remark":"java developer"
}

使用PUT请求新增文档

当指定了文档的唯一性标识(ID)时,可以使用PUT请求来新增或更新文档。如果指定的ID在索引中不存在,则会创建一个新文档;如果已存在,则会替换现有文档。语法如下:

PUT /employee/_doc/1
{
    "name":"张三",
    "sex":1,
    "age":25,
    "address":"广州天河公园",
    "remark":"java developer"
}

PUT和POST的区别

在Elasticsearch 8.x中,PUT和POST请求在新增文档时的行为有所不同,主要体现在以下几个方面:

  • 指定文档ID:

PUT请求在创建或更新文档时必须指定文档的唯一ID。如果指定的ID已经存在,PUT请求会替换现有文档;如果不存在,则创建一个新文档。
POST请求在创建新文档时可以指定ID,也可以不指定。如果不指定ID,Elasticsearch会自动生成一个唯一的ID。

  • 幂等性:

PUT请求是幂等的,这意味着多次执行相同的PUT请求,即使是针对同一个文档,最终的结果都是一致的。
POST请求不是幂等的,多次执行相同的POST请求可能会导致创建多个文档。

  • 更新行为:

PUT请求在更新文档时会替换整个文档的内容,即使是文档中未更改的部分也会被新内容覆盖。
POST请求在更新文档时可以使用_update API,这样可以只更新文档中的特定字段,而不是替换整个文档。

 批量新增文档

在Elasticsearch 8.x中,批量新增文档可以通过_bulk API来实现。这个API允许您将多个索引、更新或删除操作组合成一个单一的请求,从而提高批量操作的效率。

POST _bulk
{"create":{"_index":"article","_id":3}}
{"id":3,"title":"fox老师","content":"fox老师666","tags":["java","面向对象"],"create_time":"1739349084504"}
{"create":{"_index":"article","_id":4}}
{"id":4,"title":"mark老师","content":"mark老师NB","tags":["java","面向对象"],"create_time":"1739349084504"}

每个操作都是一个独立的JSON对象,这些对象交替出现,形成一个请求体。每个index操作后面跟着的是要索引的文档内容,update操作包含了更新的文档内容和操作类型,而delete操作则直接指明要删除的文档ID。每个操作对象的开头都必须是index、update或delete,并且每个操作之间用一个空行分隔。

_bulk API支持哪些操作类型?

Elasticsearch的_bulk API支持以下四种操作类型:

Index: 用于创建新文档或替换已有文档。
Create: 如果文档不存在则创建,如果文档已存在则返回错误。
Update: 用于更新现有文档。
Delete: 用于删除指定的文档。

Create: 如果文档不存在则创建,如果文档已存在则返回错误。

Index: 用于创建新文档或替换已有文档。

POST /employee/_bulk
{"index":{"_index":"employee","_id":1}}
{
    "name":"张三",
    "sex":1,
    "age":25,
    "address":"广州天河公园",
    "remark":"java developer"
}
{"index":{"_index":"employee","_id":2}}
{
    "name":"李四",
    "sex":1,
    "age":34,
    "address":"在私企负责研发,工作能力还算挺强的",
    "remark":"cailiao"
}
{"index":{"_index":"employee","_id":3}}
{
    "name":"Jasmine",
    "sex":1,
    "age":23,
    "address":"在长沙体制内工作",
    "remark":"在长沙体制内工作"
}
{"index":{"_index":"employee","_id":4}}
{
    "name":"鑫",
    "sex":1,
    "age":30,
    "address":"北京",
    "remark":"运维工程师"
}
{"index":{"_index":"employee","_id":5}}
{
    "name":"鑫",
    "sex":1,
    "age":34,
    "address":"四川德阳人,工作生活在深圳",
    "remark":"律师"
}
{"index":{"_index":"employee","_id":6}}
{
    "name":"Yixuan",
    "sex":1,
    "age":29,
    "address":"湖南常德人",
    "remark":"公办专科院校担任教师"
}

根据id查询文档

GET /employee/_doc/1

GET /employee/_mget
{
    "ids":["1","2","3","4","5"]
}

根据搜索关键词查询文档

在Elasticsearch 8.x中,查询文档通常使用Query DSL(Domain Specific Language),这是一种基于JSON的语言,用于构建复杂的搜索查询。

GET /employee/_search
{
    "query": {
        "term": {
          "name": {
            "value": "鑫"
          }
        }
    }
}

精确匹配 

GET /employee/_search
{
    "query": {
        "match": {
           "address": "广州天河"
        }
    }
}

范围查询
 

GET /employee/_search
{
    "query": {
        "range": {
          "age": {
            "gte": 10,
            "lte":36
          }
        }
    }
}

删除文档

批量删除文档

在Elasticsearch 8.x中,删除多个文档可以通过两种主要方法实现:

使用 _bulk API_bulk API允许您发送一系列操作请求,包括删除操作。每个删除请求是一个独立的JSON对象,格式如下:

POST _bulk
{"delete":{"_index":"employee","_id":3}}
{"delete":{"_index":"employee","_id":4}}

POST _bulk
{"delete":{"_id":3}}
{"delete":{"_id":4}}

使用 _delete_by_query API_delete_by_query API允许您根据查询条件删除文档。如果您想删除特定索引中匹配特定查询的所有文档,可以使用以下请求格式:

POST /employee/_delete_by_query
{
    "query": {
        "match": {
          "address": "广州"
        }
        
    }
}

更新文档

在Elasticsearch 8.x版本中,更新操作通常通过_update接口执行,该接口允许您部分更新现有文档的字段。以下是更新文档的基本语法:

POST /employee/_update/5
{
    "doc": {
        "age":28
    }
}

批量更新文档

在Elasticsearch 8.x中,更新多个文档可以通过两种主要方法实现:

使用 _bulk API

POST _bulk
{"update":{"_index":"employee","_id":"3"}}
{
    "doc": {
        "age":28
    }
}
{"update":{"_index":"employee","_id":"4"}}
{
    "doc": {
        "age":37
    }
}

在这个请求中,每个update块代表一个更新操作,其中_index和_id指定了要更新的文档,doc部分包含了更新后的文档内容,upsert部分定义了如果文档不存在时应该插入的内容。

 使用 _update_by_query API_update_by_query API允许您根据查询条件更新多个文档。这个操作是原子性的,意味着要么所有匹配的文档都被更新,要么一个都不会被更新。

POST /employee/_update_by_query
{
    "query": {
        "term": {
          "name": "李四"
        }
    },
    "script": {
      "source": "ctx._source.age=30",
      "lang": "painless"
    }
}

并发场景下更新文档如何保证线程安全

在Elasticsearch 7.x及以后的版本中,_seq_no和_primary_term取代了旧版本的_version字段,用于控制文档的版本。_seq_no代表文档在特定分片中的序列号,而_primary_term代表文档所在主分片的任期编号。这两个字段共同构成了文档的唯一版本标识符,用于实现乐观锁机制,确保在高并发环境下文档的一致性和正确更新。
当在高并发环境下使用乐观锁机制修改文档时,要带上当前文档的_seq_no和_primary_term进行更新:

POST /employee/_doc/1?if_seq_no=10&if_primary_term=1
{
    "name":"zhangshanxxxx",
    "sex":1,
    "age":25
}


POST /employee/_doc/1?if_seq_no=10&if_primary_term=1
{
    "name":"zhangshanxxxxdfjalkdslfk",
    "sex":1,
    "age":25
}

如果_seq_no和_primary_term不对,会抛出版本冲突异常:

{
  "error": {
    "root_cause": [
      {
        "type": "version_conflict_engine_exception",
        "reason": "[1]: version conflict, required seqNo [10], primary term [1]. current document has seqNo [0] and primary term [1]",
        "index_uuid": "tQfHiivLRmifriqpl9OdmA",
        "shard": "0",
        "index": "employee"
      }
    ],
    "type": "version_conflict_engine_exception",
    "reason": "[1]: version conflict, required seqNo [10], primary term [1]. current document has seqNo [0] and primary term [1]",
    "index_uuid": "tQfHiivLRmifriqpl9OdmA",
    "shard": "0",
    "index": "employee"
  },
  "status": 409
}

实践练习:实现某金融企业理财平台的理财产品信息检索功能

PUT /product_info
{
    "settings":{
        "number_of_shards": 1,
        "number_of_replicas": 1
    },
    "mappings":{
        "properties": {
            "productName":{
                "type": "text",
                "analyzer": "standard"
            },
            "annual_rate":{
                "type": "keyword"
            },
            "age":{
                "type": "integer"
            },
            "describe":{
                "type": "text",
                "analyzer": "standard"
            }
        }
    }
}
POST /product_info/_bulk
{"index":{}}
{"productName":"理财产品A","annual_rate":"3.2200%","describe":"180天定期理财,最低20000起投,收益稳定,可以自助选择消息推送"}
{"index":{}}
{"productName":"理财产品B","annual_rate":"3.1100%","describe":"90天定投产品,最低10000起投,每天收益到账消息推送"}
{"index":{}}
{"productName":"理财产品C","annual_rate":"3.3500%","describe":"270天定投产品,最低40000起投,每天收益立即到账消息推送"}
{"index":{}}
{"productName":"理财产品D","annual_rate":"3.1200%","describe":"90天定投产品,最低12000起投,每天收益到账消息推送"}
{"index":{}}
{"productName":"理财产品E","annual_rate":"3.0100%","describe":"30天定投产品推荐,最低8000起投,每天收益会消息推送"}
{"index":{}}
{"productName":"理财产品F","annual_rate":"2.7500%","describe":"热门短期产品,3天短期,无须任何手续费用,最低500起投,通过短信提示获取收益消息"}

全文搜索

GET /product_info/_search
{
    "query": {
        "match": {
          "describe": "每天收益到账消息推送"
        }
    }
}

搜索年化率在3.0000%到3.1300%之间的产品。

GET /product_info/_search
{
    "query": {
        "range": {
          "annual_rate": {
            "gte": "3.0000%",
            "lte": "3.1300%"
          }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值