ElasticSearch基础数据管理-3-文档操作详解

 

ElasticSearch基础数据管理-3-文档操作详解

 

1、简介

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

2、文档的基本操作

以下操作基于 Elasticsearch 7.x 及以上版本。

1、新增文档

新增文档的操作可以通过POST或PUT请求完成,具体取决于是否指定了文档的唯一性标识(即ID)。如果在创建数据时指定了唯一性标识,可以使用POST或PUT请求;如果没有指定唯一性标识,只能使用POST请求。

1.1 指定ID创建(PUT)

PUT /<index>/_doc/<_id>
{
  "field1": "value1",
  "field2": "value2"
}

# 示例:创建商品文档
PUT /products/_doc/1001
{
  "name": "iPhone 15 Pro",
  "price": 8999,
  "category": "电子产品",
  "stock": 50,
  "tags": ["手机", "苹果", "旗舰"],
  "specs": {
    "color": "深空黑",
    "storage": "256GB"
  },
  "created_at": "2024-12-01T10:30:00"
}

# 响应示例
{
  "_index": "products",
  "_id": "1001",
  "_version": 1,
  "result": "created",
  "_shards": { "total": 2, "successful": 1, "failed": 0 },
  "_seq_no": 0,
  "_primary_term": 1
}

1.2 自动生成ID创建(POST)

POST /products/_doc/
{
  "name": "MacBook Pro",
  "price": 12999
}

# 响应包含自动生成的ID
{
  "_id": "abc123def456"
}

1.3 创建时指定操作类型

PUT /products/_create/1002  # 如果文档已存在则失败
{
  "name": "iPad"
}
# 或
PUT /products/_doc/1002?op_type=create

 

2、获取文档

2.1 获取单个文档

GET /products/_doc/1001

# 响应
{
  "_index": "products",
  "_id": "1001",
  "_version": 2,
  "_seq_no": 1,
  "_primary_term": 1,
  "found": true,
  "_source": {
    "name": "iPhone 15 Pro",
    "price": 8999,
    "category": "电子产品"
  }
}

2.2 获取多个文档(mget)

GET /_mget
{
  "docs": [
    { "_index": "products", "_id": "1001" },
    { "_index": "products", "_id": "1002" },
    { "_index": "users", "_id": "user_001" }
  ]
}

# 或指定索引
GET /products/_mget
{
  "ids": ["1001", "1002", "1003"]
}

其他操作

# 2.3 只获取特定字段
GET /products/_doc/1001?_source=name,price

# 2.4 排除特定字段
GET /products/_doc/1001?_source_exclude=tags,specs

# 2.5 只获取_source部分
GET /products/_source/1001

# 2.6 检查文档是否存在
HEAD /products/_doc/1001  # 返回200存在,404不存在
 
2.3、根据搜索关键词查询文档
查询文档通常使用Query DSL(Domain Specific Language),这是一种基于JSON的语言,用于构建复杂的搜索查询。
GET /<index_name>/_search
{
 "query": {
     # - 匹配所有文档
    "match_all": {}
    # - 文本字段匹配
    "match": {
      "<field_name>": "<query_string>"
    }
    # - 精确匹配(不分词)
    "term": {
          "<field_name>": {
            "value": "<exact_value>"
          }
        }
    # 范围查询
    "range": {
      "<field_name>": {
        "gte": <lower_bound>,
        "lte": <upper_bound>
      }
    }
 }
}

 

3、更新文档

3.1 全量替换(PUT)当前更新不存在字段也会被替换掉

PUT /products/_doc/1001
{
  "name": "iPhone 15 Pro Updated",
  "price": 8499,  # 注意:未包含的字段会被删除!
  "category": "电子产品"
}

3.2 部分更新(推荐)

POST /products/_update/1001
{
  "doc": {
    "price": 8199,
    "stock": 45,
    "new_field": "促销中"
  }
}

3.3 使用脚本更新

POST /products/_update/1001
{
  "script": {
    "source": """
      // 增加价格
      ctx._source.price += 100;
      
      // 减少库存
      if (ctx._source.containsKey('stock')) {
        ctx._source.stock -= params.sold;
      }
      
      // 添加标签
      if (!ctx._source.tags.contains(params.newTag)) {
        ctx._source.tags.add(params.newTag);
      }
      
      // 设置更新时间
      ctx._source.updated_at = params.now;
    """,
    "params": {
      "sold": 5,
      "newTag": "促销",
      "now": "2024-12-02T09:00:00"
    },
    "lang": "painless"
  }
}

3.4 条件更新(只有文档存在时才更新)

POST /<index_name>/_update_by_query
{
 "query": {
    <!-- 定义更新文档的查询条件 -->
 },
 "script": {
    "source": "ctx._source.field = 'new_value'",
    "lang": "painless"
 }
}
在这个请求中,<index_name>是您要更新的索引名称,query部分定义了哪些文档需要被更新,script部分定义了如何更新这些文档的字段。
并发场景下更新文档如何保证线程安全?
在Elasticsearch 7.x及以后的版本中,_seq_no和_primary_term取代了旧版本的_version字段,用于控制文档的版本。_seq_no代表文档在特定分片中的序列号,而_primary_term代表文档所在主分片的任期编号。这两个字段共同构成了文档的唯一版本标识符,用于实现乐观锁机制,确保在高并发环境下文档的一致性和正确更新。
当在高并发环境下使用乐观锁机制修改文档时,要带上当前文档的_seq_no和_primary_term进行更新:
如果_seq_no和_primary_term不对,会抛出版本冲突异常。
POST /employee/_doc/1?if_seq_no=13&if_primary_term=1
{
  "name": "张三xxxx",
  "sex": 1,
  "age": 25
}

以前的使用版本号

POST /products/_update/1001?version=2&version_type=external
{
  "doc": { "price": 7999 }
}

更新时重试冲突(乐观锁)

POST /products/_update/1001?retry_on_conflict=3
{
  "doc": { "stock": 40 }
}

 

4、 删除文档

 4.1 删除单个文档

DELETE /products/_doc/1001

# 响应
{
  "_index": "products",
  "_id": "1001",
  "_version": 3,
  "result": "deleted",
  "_shards": { "total": 2, "successful": 1, "failed": 0 },
  "_seq_no": 3,
  "_primary_term": 1
}

4.2 按条件删除文档

POST /products/_delete_by_query
{
  "query": {
    "range": {
      "price": { "lt": 1000 }
    }
  }
}

4.3 删除多个文档(使用 mdelete)

POST /products/_bulk
{ "delete": { "_id": "1001" } }
{ "delete": { "_id": "1002" } }

# 4.4 删除所有文档(保留索引结构)
POST /products/_delete_by_query
{
  "query": {
    "match_all": {}
  }
}

 

5、批量操作

批量新增文档可以通过_bulk API来实现。这个API允许您将多个索引、更新或删除操作组合成一个单一的请求,从而提高批量操作的效率。
Elasticsearch的_bulk API支持以下四种操作类型:
  • Index: 用于创建新文档或替换已有文档。
  • Create: 如果文档不存在则创建,如果文档已存在则返回错误。
  • Update: 用于更新现有文档。
  • Delete: 用于删除指定的文档。
# Bulk 操作格式:每行一个操作说明,下一行为数据(delete没有数据行)
POST /_bulk
{ "index": { "_index": "products", "_id": "2001" } }
{ "name": "小米13", "price": 3999, "category": "手机" }
{ "delete": { "_index": "products", "_id": "1001" } }
{ "create": { "_index": "products", "_id": "2002" } }
{ "name": "华为Mate60", "price": 6999 }
{ "update": { "_index": "products", "_id": "2002" } }
{ "doc": { "stock": 30 } }

 

 

 
 
 

 

posted @ 2026-01-05 21:17  邓维-java  阅读(1)  评论(0)    收藏  举报