Cập Nhật Bổ Sung Trong Elasticsearch: Sử Dụng Partial Update Hiệu Quả

Tại sao cần cập nhật bổ sung?

Thay vì sử dụng PUT để thay thế toàn bộ tài liệu (tốn kém hiệu năng do phải đọc, sửa, ghi lại), Elasticsearch cung cấp cơ chế _update cho phép chỉnh sửa từng trường cụ thể. Phương pháp này tránh được các bước trung gian như:

  • Truy vấn shard chứa tài liệu → Trả về bộ nhớ → Chỉnh sửa → Gửi lại shard → Ghi chỉ mục
  • Giảm thiểu xung đột đồng thời nhờ thực hiện tất cả thao tác trong cùng shard

Cách triển khai cơ bản

Thay vì sử dụng POST index/type/id (gây mất dữ liệu), dùng _update để cập nhật từng trường:

// Tạo mẫu dữ liệu
PUT company/employee/1001
{
  "user_name": "Tran Van A",
  "current_age": 28,
  "salary": 12000
}

// Cập nhật bổ sung trường tuổi
POST company/employee/1001/_update
{
  "doc": {
    "current_age": 29
  }
}

Quan trọng: Nếu dùng POST company/employee/1001 thay vì _update, toàn bộ tài liệu sẽ bị ghi đè → trường salary sẽ mất đi.

Xử lý phức tạp với script

Painless script tích hợp (ưu tiên)

// Tăng lương 10% bằng script
POST company/employee/1001/_update
{
  "script": {
    "source": "ctx._source.salary *= params.raise_factor",
    "params": {
      "raise_factor": 1.1
    }
  }
}

Script Groovy (đã lỗi thời)

(Chỉ hỗ trợ trên ES 5.x, ES 6+ không còn hỗ trợ)

// Lưu script vào ${ES_HOME}/config/scripts/increase_salary.groovy
// Nội dung: ctx._source.salary *= bonus

POST company/employee/1001/_update
{
  "script": {
    "lang": "groovy",
    "file": "increase_salary",
    "params": {
      "bonus": 1.1
    }
  }
}

Lưu ý: Hệ thống báo Deprecation: [groovy] scripts are deprecated. Nên sử dụng painless thay thế.

Chế độ upsert khi tài liệu không tồn tại

// Nếu tài liệu id=1001 không tồn tại, tự tạo mới với trường level
POST company/employee/1001/_update
{
  "script": "ctx._source.level = params.new_level",
  "upsert": {
    "user_name": "New Employee",
    "level": 0
  },
  "params": {
    "new_level": 3
  }
}

Kết quả: "result": "created" nếu tài liệu chưa tồn tại.

Điều khiển xung đột đồng thời

Tham số retry_on_conflict xác định số lần thử lại khi xung đột:

POST company/employee/1001/_update?retry_on_conflict=3

Cơ chế hoạt động:

  1. Client A và B cùng đọc tài liệu với _version=1
  2. Client A cập nhật thành công → _version=2
  3. Client B cập nhật → phát hiện _version=1 ≠ 2 → xung đột
  4. Client B tự động thử lại retry_on_conflict lần (mặc định 0)

Thẻ: elasticsearch-painless document-partial-update concurrency-control

Đăng vào ngày 23 tháng 7 lúc 13:21