paint-brush
Hướng dẫn đơn giản để cập nhật tài liệu trong Elaticsearchtừ tác giả@rocksetcloud
6,621 lượt đọc
6,621 lượt đọc

Hướng dẫn đơn giản để cập nhật tài liệu trong Elaticsearch

từ tác giả Rockset9m2024/04/12
Read on Terminal Reader

dài quá đọc không nổi

Blog này khám phá các chiến lược thiết yếu để xử lý các bản cập nhật trong Elaticsearch, rất quan trọng đối với các ứng dụng tìm kiếm và phân tích. Tìm hiểu về các bản cập nhật đầy đủ, bản cập nhật một phần và bản cập nhật theo tập lệnh, cùng với ý nghĩa của chúng đối với việc sử dụng CPU. Khám phá các lựa chọn thay thế như Rockset để quản lý hiệu quả các sửa đổi tài liệu thường xuyên.
featured image - Hướng dẫn đơn giản để cập nhật tài liệu trong Elaticsearch
Rockset HackerNoon profile picture
0-item
1-item



Elaticsearch là một công cụ phân tích và tìm kiếm nguồn mở dựa trên Apache Lucene. Khi xây dựng các ứng dụng trên dữ liệu thu thập dữ liệu thay đổi (CDC) bằng Elaticsearch, bạn sẽ muốn kiến trúc hệ thống để xử lý các bản cập nhật hoặc sửa đổi thường xuyên đối với các tài liệu hiện có trong một chỉ mục.


Trong blog này, chúng tôi sẽ giới thiệu các tùy chọn khác nhau có sẵn cho các bản cập nhật bao gồm cập nhật đầy đủ, cập nhật một phần và cập nhật theo tập lệnh. Chúng ta cũng sẽ thảo luận về những gì xảy ra trong Elaticsearch khi sửa đổi tài liệu và mức độ ảnh hưởng của các bản cập nhật thường xuyên đến việc sử dụng CPU trong hệ thống.

Ứng dụng mẫu có cập nhật thường xuyên

Để hiểu rõ hơn về các trường hợp sử dụng có cập nhật thường xuyên , hãy xem ứng dụng tìm kiếm cho dịch vụ phát video trực tuyến như Netflix. Khi người dùng tìm kiếm một chương trình, tức là “phim kinh dị chính trị”, họ sẽ được trả về một tập hợp các kết quả có liên quan dựa trên từ khóa và siêu dữ liệu khác.


Hãy xem một tài liệu ví dụ trong Elaticsearch của chương trình “House of Cards”:

 { "name": "House of Cards", "description": "Frank Underwood is a Democrat appointed as the Secretary of State. Along with his wife, he sets out on a quest to seek revenge from the people who betrayed him while successfully rising to supremacy.", "genres": ["drama", "thriller"], "views": 100, }


Tìm kiếm có thể được định cấu hình trong Elaticsearch để sử dụng namedescription làm trường tìm kiếm toàn văn bản. Trường views , nơi lưu trữ số lượt xem cho mỗi tiêu đề, có thể được sử dụng để quảng bá nội dung, xếp hạng các chương trình phổ biến hơn cao hơn. Trường views tăng lên mỗi khi người dùng xem một tập của chương trình hoặc phim.


Khi sử dụng cấu hình tìm kiếm này trong một ứng dụng có quy mô như Netflix , số lượng cập nhật được thực hiện có thể dễ dàng vượt qua hàng triệu bản mỗi phút theo xác định của Báo cáo mức độ tương tác của Netflix . Theo Báo cáo, người dùng đã xem ~100 tỷ giờ nội dung từ tháng 1 đến tháng 7. Giả sử thời lượng xem trung bình mỗi tập hoặc một bộ phim là 15 phút thì số lượt xem mỗi phút trung bình đạt 1,3 triệu. Với cấu hình tìm kiếm được chỉ định ở trên, mỗi chế độ xem sẽ yêu cầu cập nhật ở quy mô hàng triệu.


Nhiều ứng dụng tìm kiếm và phân tích có thể gặp phải các bản cập nhật thường xuyên, đặc biệt khi được xây dựng trên dữ liệu CDC.

Thực hiện cập nhật trong Elaticsearch

Hãy cùng đi sâu vào một ví dụ chung về cách thực hiện cập nhật trong Elaticsearch bằng mã bên dưới:

 - from elasticsearch import Elasticsearch # Connect to your Elasticsearch instance es = Elasticsearch([{'host': 'localhost', 'port': 9200}]) # Index name and document ID you want to update index_name = 'movies' document_id = 'your_document_id' # Retrieve the current document to get the current 'views' value try: current_doc = es.get(index=index_name, id=document_id) current_views = current_doc['_source']['views'] except Exception as e: print(f"Error retrieving current document: {e}") current_views = 0 # Set a default value if there's an error # Define the update body to increment 'views' by 1 update_body = { "doc": { "views": current_views + 1 # Increment 'views' by 1 } } # Perform the update try: es.update(index=index_name, id=document_id, body=update_body) print("Document updated successfully!") except Exception as e: print(f"Error updating document: {e}")


Cập nhật đầy đủ so với cập nhật một phần trong Elaticsearch

Khi thực hiện cập nhật trong Elasticsearch, bạn có thể sử dụng API chỉ mục để thay thế tài liệu hiện có hoặc API cập nhật để cập nhật một phần tài liệu.


API chỉ mục truy xuất toàn bộ tài liệu, thực hiện các thay đổi đối với tài liệu và sau đó lập chỉ mục lại tài liệu. Với API cập nhật, bạn chỉ cần gửi các trường bạn muốn sửa đổi thay vì toàn bộ tài liệu. Điều này vẫn khiến tài liệu được lập chỉ mục lại nhưng giảm thiểu lượng dữ liệu được gửi qua mạng. API cập nhật đặc biệt hữu ích trong trường hợp kích thước tài liệu lớn và việc gửi toàn bộ tài liệu qua mạng sẽ tốn thời gian.


Hãy xem cách cả API chỉ mục và API cập nhật hoạt động bằng mã Python.

Cập nhật đầy đủ bằng API chỉ mục trong Elaticsearch

 from elasticsearch import Elasticsearch # Connect to Elasticsearch es = Elasticsearch([{'host': 'localhost', 'port': 9200}]) # Index name and document ID index_name = "your_index" document_id = "1" # Retrieve the existing document existing_document = es.get(index=index_name, id=document_id) # Make your changes to the document existing_document["_source"]["field1"] = "new_value1" existing_document["_source"]["field2"] = "new_value2" # Call the index API to perform the full update es.index(index=index_name, id=document_id, body=existing_document["_source"])


Như bạn có thể thấy trong đoạn mã trên, API chỉ mục yêu cầu hai lệnh gọi riêng biệt tới Elaticsearch, điều này có thể dẫn đến hiệu suất chậm hơn và tải trên cụm của bạn cao hơn.


Cập nhật một phần bằng API cập nhật trong Elaticsearch

Các bản cập nhật một phần sử dụng API reindex nội bộ nhưng đã được định cấu hình để chỉ yêu cầu một lệnh gọi mạng duy nhất để có hiệu suất tốt hơn.


 from elasticsearch import Elasticsearch # Connect to Elasticsearch es = Elasticsearch([{'host': 'localhost', 'port': 9200}]) # Index name and document ID index_name = "your_index" document_id = "1" # Specify the fields to be updated update_fields = { "field1": "new_value1", "field2": "new_value2" } # Use the update API to perform a partial update es.update(index=index_name, id=document_id, body={"doc": update_fields})


Bạn có thể sử dụng API cập nhật trong Elaticsearch để cập nhật số lượt xem nhưng bản thân API cập nhật không thể được sử dụng để tăng số lượt xem dựa trên giá trị trước đó. Đó là vì chúng tôi cần số lượt xem cũ hơn để đặt giá trị số lượt xem mới.


Hãy xem cách chúng ta có thể khắc phục điều này bằng cách sử dụng ngôn ngữ kịch bản mạnh mẽ, Painless.


Cập nhật một phần bằng cách sử dụng tập lệnh Painless trong Elaticsearch

Painless là ngôn ngữ kịch bản được thiết kế cho Elaticsearch và có thể được sử dụng để tính toán truy vấn và tổng hợp, các điều kiện phức tạp, chuyển đổi dữ liệu, v.v. Không đau cũng cho phép sử dụng tập lệnh trong truy vấn cập nhật để sửa đổi tài liệu dựa trên logic phức tạp.


Trong ví dụ bên dưới, chúng tôi sử dụng tập lệnh Painless để thực hiện cập nhật trong một lệnh gọi API và tăng số lượt xem mới dựa trên giá trị của số lượt xem cũ.


 from elasticsearch import Elasticsearch # Connect to your Elasticsearch instance es = Elasticsearch([{'host': 'localhost', 'port': 9200}]) # Index name and document ID you want to update index_name = 'movies' document_id = 'your_document_id' # Define the Painless script for the update update_script = { "script": { "lang": "painless", "source": "ctx._source.views += 1" # Increment 'views' by 1 } } # Perform the update using the Painless script try: es.update(index=index_name, id=document_id, body=update_script) print("Document updated successfully!") except Exception as e: print(f"Error updating document: {e}")


Tập lệnh Painless khá trực quan để hiểu, nó chỉ đơn giản là tăng số lượt xem lên 1 cho mỗi tài liệu.


Cập nhật một đối tượng lồng nhau trong Elaticsearch

Các đối tượng lồng nhau trong Elaticsearch là một cấu trúc dữ liệu cho phép lập chỉ mục các mảng đối tượng dưới dạng các tài liệu riêng biệt trong một tài liệu gốc. Các đối tượng lồng nhau rất hữu ích khi xử lý dữ liệu phức tạp tạo thành cấu trúc lồng nhau một cách tự nhiên, giống như các đối tượng bên trong các đối tượng. Trong tài liệu Elaticsearch điển hình, các mảng đối tượng được làm phẳng nhưng việc sử dụng kiểu dữ liệu lồng nhau cho phép mỗi đối tượng trong mảng được lập chỉ mục và truy vấn một cách độc lập.


Các tập lệnh dễ dàng cũng có thể được sử dụng để cập nhật các đối tượng lồng nhau trong Elaticsearch.

 from elasticsearch import Elasticsearch # Connect to your Elasticsearch instance es = Elasticsearch([{'host': 'localhost', 'port': 9200}]) # Index name and document ID for the example index_name = 'your_index' document_id = 'your_document_id' # Specify the nested field and the updated value nested_field = "nested_field_name" updated_value = "new_value" # Define the Painless script for the update update_script = { "script": { "lang": "painless", "source": "ctx._source.nested_field_name = params.updated_value", "params": { "updated_value": updated_value } } } # Perform the update using the Update API and the Painless script try: es.update(index=index_name, id=document_id, body=update_script) print("Nested object updated successfully!") except Exception as e: print(f"Error updating nested object: {e}")


Thêm một trường mới trong Elaticsearch

Việc thêm trường mới vào tài liệu trong Elaticsearch có thể được thực hiện thông qua thao tác chỉ mục.


Bạn có thể cập nhật một phần tài liệu hiện có với trường mới bằng API cập nhật. Khi bật ánh xạ động trên chỉ mục, việc giới thiệu trường mới rất đơn giản. Chỉ cần lập chỉ mục tài liệu chứa trường đó và Elaticsearch sẽ tự động tìm ra ánh xạ phù hợp và thêm trường mới vào ánh xạ.


Khi tính năng ánh xạ động trên chỉ mục bị tắt, bạn sẽ cần sử dụng API ánh xạ cập nhật. Bạn có thể xem ví dụ bên dưới về cách cập nhật ánh xạ chỉ mục bằng cách thêm trường “danh mục” vào chỉ mục phim.


 PUT /movies/_mapping { "properties": { "category": { "type": "keyword" } } }


Cập nhật trong Elaticsearch Under the Hood

Mặc dù mã đơn giản nhưng nội bộ Elaticsearch đang thực hiện rất nhiều công việc nặng nhọc để thực hiện các cập nhật này vì dữ liệu được lưu trữ trong các phân đoạn bất biến. Do đó, Elaticsearch không thể đơn giản thực hiện cập nhật tại chỗ cho tài liệu. Cách duy nhất để thực hiện cập nhật là lập chỉ mục lại toàn bộ tài liệu, bất kể API nào được sử dụng.


Elaticsearch sử dụng Apache Lucene dưới mui xe. Chỉ mục Lucene bao gồm một hoặc nhiều phân đoạn. Phân đoạn là một cấu trúc chỉ mục độc lập, bất biến, đại diện cho một tập hợp con của chỉ mục tổng thể. Khi tài liệu được thêm hoặc cập nhật, các phân đoạn Lucene mới sẽ được tạo và các tài liệu cũ hơn sẽ được đánh dấu để xóa mềm. Theo thời gian, khi các tài liệu mới được thêm vào hoặc các tài liệu hiện có được cập nhật, nhiều phân đoạn có thể được tích lũy. Để tối ưu hóa cấu trúc chỉ mục, Lucene định kỳ hợp nhất các phân đoạn nhỏ hơn thành các phân đoạn lớn hơn.

Các bản cập nhật về cơ bản là phần chèn vào Elaticsearch

Vì mỗi thao tác cập nhật là một thao tác reindex nên tất cả các bản cập nhật về cơ bản đều là các thao tác chèn và xóa mềm.


Có những tác động về mặt chi phí khi xử lý bản cập nhật như một thao tác chèn. Một mặt, việc xóa mềm dữ liệu có nghĩa là dữ liệu cũ vẫn được giữ lại trong một thời gian, làm tăng dung lượng lưu trữ và bộ nhớ của chỉ mục. Việc thực hiện các thao tác xóa mềm, lập chỉ mục lại và thu gom rác cũng gây tổn thất nặng nề cho CPU, tổn thất sẽ càng trầm trọng hơn khi lặp lại các thao tác này trên tất cả các bản sao.


Việc cập nhật có thể phức tạp hơn khi sản phẩm của bạn phát triển và dữ liệu của bạn thay đổi theo thời gian. Để giữ cho Elaticsearch hoạt động hiệu quả, bạn sẽ cần cập nhật các phân đoạn, bộ phân tích và bộ mã thông báo trong cụm của mình, yêu cầu lập chỉ mục lại toàn bộ cụm. Đối với các ứng dụng sản xuất, điều này sẽ yêu cầu thiết lập một cụm mới và di chuyển tất cả dữ liệu sang. Việc di chuyển các cụm vừa tốn thời gian vừa dễ xảy ra lỗi nên đây không phải là một thao tác được xem nhẹ.

Cập nhật trong Elaticsearch

Sự đơn giản của các hoạt động cập nhật trong Elaticsearch có thể che giấu các tác vụ vận hành nặng nề diễn ra trong hệ thống. Elaticsearch coi mỗi bản cập nhật là một phần chèn, yêu cầu toàn bộ tài liệu phải được tạo lại và lập chỉ mục lại. Đối với các ứng dụng có bản cập nhật thường xuyên, điều này có thể nhanh chóng trở nên tốn kém như chúng ta đã thấy trong ví dụ về Netflix, nơi có hàng triệu bản cập nhật diễn ra mỗi phút. Chúng tôi khuyên bạn nên cập nhật theo đợt bằng cách sử dụng API hàng loạt để tăng thêm độ trễ cho khối lượng công việc của bạn hoặc xem xét các giải pháp thay thế khi gặp phải các bản cập nhật thường xuyên trong Elaticsearch.


Rockset, cơ sở dữ liệu tìm kiếm và phân tích được xây dựng trên đám mây, là một giải pháp thay thế có thể thay đổi cho Elaticsearch. Được xây dựng trên RocksDB , một kho lưu trữ khóa-giá trị phổ biến nhờ khả năng thay đổi của nó, Rockset có thể thực hiện cập nhật tại chỗ cho các tài liệu. Điều này dẫn đến chỉ giá trị của các trường riêng lẻ được cập nhật và lập chỉ mục lại thay vì toàn bộ tài liệu.


Nếu muốn so sánh hiệu suất của Elasticsearch và Rockset đối với khối lượng công việc phải cập nhật nhiều, bạn có thể bắt đầu dùng thử Rockset miễn phí với khoản tín dụng 300 USD.