Tương tự như cách chúng ta thực hiện các thao tác tạo, đọc, cập nhật và xóa (CRUD) trên cơ sở dữ liệu quan hệ, dữ liệu được lưu trữ trong kho chỉ mục (Index Repository) của Lucene cũng đòi hỏi các quy trình quản lý tương ứng để duy trì tính toàn vẹn và hiệu quả tìm kiếm.
Xóa chỉ mục theo điều kiện (Term)
Để loại bỏ một tài liệu cụ thể khỏi chỉ mục, Lucene cung cấp cơ chế xóa dựa trên đối tượng Term. Quy trình này đòi hỏi trường dữ liệu được sử dụng để làm điều kiện xóa phải là một trường duy nhất (ví dụ: ID) và không được trải qua quá trình phân tách từ (tokenized).
Các bước thực hiện bao gồm:
- Khởi tạo đối tượng
Analyzerđể xử lý văn bản. - Cấu hình Lucene thông qua
IndexWriterConfig. - Chỉ định đường dẫn thư mục chứa chỉ mục bằng
Directory. - Tạo đối tượng
IndexWriterđể thực hiện ghi dữ liệu. - Xác định điều kiện xóa bằng đối tượng
Term. - Gọi phương thức xóa và đóng tài nguyên.
/**
* Thực hiện xóa tài liệu dựa trên Term
*/
@Test
public void removeDocumentByTerm() throws IOException {
// 1. Khởi tạo Analyzer (sử dụng StandardAnalyzer hoặc IKAnalyzer tùy ngữ cảnh)
Analyzer textAnalyzer = new StandardAnalyzer();
// 2. Cấu hình thông số cho IndexWriter
IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_4_10_4, textAnalyzer);
// 3. Mở thư mục lưu trữ index
Directory storageDir = FSDirectory.open(new File("/path/to/index/storage"));
// 4. Khởi tạo IndexWriter để thao tác trên index
IndexWriter idxModifier = new IndexWriter(storageDir, config);
// 5. Tạo điều kiện xóa (Term)
// Ví dụ: Xóa các tài liệu có trường "bookName" chứa từ khóa "java"
Term searchCondition = new Term("bookName", "java");
// 6. Thực hiện lệnh xóa
// Lucene chấp nhận nhiều điều kiện cùng lúc
idxModifier.deleteDocuments(searchCondition);
// 7. Đóng kết nối và giải phóng tài nguyên
idxModifier.close();
}
Lưu ý rằng, khi thực hiện deleteDocuments, Lucene thực hiện "xóa mềm" (soft delete). Nó không xóa dữ liệu ngay lập tức mà đánh dấu các tệp tin là đã xóa (trong tệp .del). Việc này giúp tối ưu hiệu suất, dữ liệu thực sự sẽ bị xóa khi quá trình tối ưu hóa (merge) diễn ra.
Xóa toàn bộ chỉ mục
Thao tác này sẽ loại bỏ toàn bộ dữ liệu trong kho chỉ mục, bao gồm cả lĩnh vực tài liệu (Stored Fields) và lĩnh vực chỉ mục (Indexed Fields). Hành vi này tương tự như lệnh TRUNCATE trong SQL, nơi dữ liệu và cấu trúc liên quan bị xóa sạch.
Các bước thực hiện tương tự như trên, thay vì truyền điều kiện, chúng ta gọi phương thức xóa tất cả.
/**
* Xóa toàn bộ dữ liệu trong index
*/
@Test
public void clearAllIndexes() throws IOException {
// 1. Khởi tạo Analyzer
Analyzer tokenizer = new StandardAnalyzer();
// 2. Cấu hình IndexWriter
IndexWriterConfig cfg = new IndexWriterConfig(Version.LUCENE_4_10_4, tokenizer);
// 3. Chỉ định thư mục chỉ mục
Directory dirLocation = FSDirectory.open(new File("/path/to/index/storage"));
// 4. Tạo đối tượng ghi
IndexWriter writer = new IndexWriter(dirLocation, cfg);
// 5. Thực hiện xóa toàn bộ
writer.deleteAll();
// 6. Đóng writer
writer.close();
}
Hành động này cần được cân nhắc kỹ lưỡng vì không thể hoàn tác sau khi thực hiện.
Cập nhật chỉ mục
Trong Lucene, không có phương thức cập nhật trực tiếp (update) theo nghĩa đen của cơ sở dữ liệu. Thay vào đó, thao tác cập nhật được thực hiện theo nguyên tắc: Xóa tài liệu cũ (dựa trên Term) và sau đó thêm tài liệu mới vào vị trí đó.
Logic hoạt động như sau:
- Nếu tìm thấy tài liệu khớp với
Term: Xóa tài liệu cũ và thêm tài liệu mới. - Nếu không tìm thấy tài liệu khớp với
Term: Thêm tài liệu mới như một bản ghi mới (tương tự thao tác Insert).
/**
* Cập nhật tài liệu trong index
*/
@Test
public void modifyDocument() throws IOException {
// 1. Tạo Analyzer
Analyzer analyzer = new StandardAnalyzer();
// 2. Cấu hình Lucene
IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_4_10_4, analyzer);
// 3. Mở Directory
Directory directory = FSDirectory.open(new File("/path/to/index/storage"));
// 4. Tạo IndexWriter
IndexWriter writer = new IndexWriter(directory, iwc);
// 5. Tạo Document mới chứa dữ liệu cập nhật
Document updatedDoc = new Document();
updatedDoc.add(new TextField("id", "1234", Store.YES));
// Giả sử thay đổi nội dung tên sách
updatedDoc.add(new TextField("name", "Lập trình Java nâng cao", Store.YES));
// 6. Tạo điều kiện để tìm tài liệu cần cập nhật (Term)
// Lucene sẽ tìm tài liệu có trường 'name' là 'Java cơ bản' để thay thế
Term updateCondition = new Term("name", "Java cơ bản");
// 7. Thực hiện cập nhật
// Nếu không tìm thấy 'Java cơ bản', Document mới sẽ được thêm vào
writer.updateDocument(updateCondition, updatedDoc);
// 8. Đóng tài nguyên
writer.close();
}