1. Hiển thị nổi bật là gì
Hiển thị nổi bật là một tính năng của hệ thống tìm kiếm toàn văn, cho phép làm nổi bật các từ khóa trong kết quả tìm kiếm (thường là in đậm và tô màu).
2. Triển khai hiển thị nổi bật
Lucene cung cấp các thành phần hỗ trợ hiển thị nổi bật.
2.1 Cấu hình pom.xml để thêm hỗ trợ hiển thị nổi bật
<project>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- phiên bản mysql -->
<mysql.version>5.1.30</mysql.version>
<!-- phiên bản lucene -->
<lucene.version>4.10.3</lucene.version>
<!-- phiên bản bộ tách từ ik -->
<ik.version>2012_u6</ik.version>
</properties>
<dependencies>
// ......
<!-- lucene highlighter -->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-highlighter</artifactId>
<version>${lucene.version}</version>
</dependency>
</dependencies>
</project>
2.2 Triển khai mã nguồn
Các bước thực hiện:
- Tạo đối tượng điểm số (QueryScorer) để tính điểm cho nội dung hiển thị nổi bật
- Tạo đối tượng phân đoạn (Fragmenter) để cắt nội dung hiển thị nổi bật
- Tạo đối tượng thành phần hiển thị nổi bật (Highlighter)
- Tạo đối tượng phân tích (Analyzer) để tách từ
- Sử dụng lớp TokenSources để lấy đối tượng luồng (TokenStream)
- Sử dụng đối tượng Highlighter để hoàn thành hiển thị nổi bật
/**
* Đóng gói phương thức tìm kiếm (phương thức hiển thị nổi bật)
*/
private void timKiemVaNenSang(Query query) throws Exception {
// In cú pháp truy vấn được tạo bởi đối tượng Query
System.out.println("Cú pháp truy vấn: " + query);
// 1. Tạo đối tượng vị trí thư mục chỉ mục (Directory), chỉ định vị trí thư mục chỉ mục
Directory thuMucChiMuc = FSDirectory.open(new File("/Users/healchow/Documents/index"));
// 2. Tạo đối tượng đọc chỉ mục (IndexReader), dùng để đọc dữ liệu chỉ mục vào bộ nhớ
IndexReader docDoc = DirectoryReader.open(thuMucChiMuc);
// 3. Tạo đối tượng tìm kiếm chỉ mục (IndexSearcher), dùng để thực thi tìm kiếm
IndexSearcher timKiemChiMuc = new IndexSearcher(docDoc);
// 4. Sử dụng đối tượng IndexSearcher để thực thi tìm kiếm, trả về tập kết quả TopDocs
// Tham số 1: đối tượng truy vấn sử dụng, Tham số 2: chỉ định n kết quả được sắp xếp đầu tiên cần trả về
TopDocs topDocs = timKiemChiMuc.search(query, 10);
// Thêm xử lý hiển thị nổi bật ============================== bắt đầu
// 1. Tạo đối tượng điểm số (QueryScorer), dùng để đánh điểm cho nội dung hiển thị nổi bật
QueryScorer diemSo = new QueryScorer(query);
// 2. Tạo đối tượng phân đoạn (Fragmenter), dùng để cắt nội dung hiển thị nổi bật
Fragmenter phanDoan = new SimpleSpanFragmenter(diemSo);
// 3. Tạo đối tượng thành phần hiển thị nổi bật (Highlighter)
Highlighter thanhPhanNenSang = new Highlighter(diemSo);
// Đặt đối tượng phân đoạn
thanhPhanNenSang.setTextFragmenter(phanDoan);
// 4. Tạo đối tượng phân tích (Analyzer), dùng để tách từ
Analyzer phanTich = new IKAnalyzer();
// Thêm xử lý hiển thị nổi bật ============================== kết thúc
// 5. Xử lý tập kết quả
// 5.1 In số lượng kết quả thực tế được truy vấn
System.out.println("Số lượng kết quả thực tế được truy vấn: " + topDocs.totalHits);
// 5.2 Lấy mảng kết quả tìm kiếm
// ScoreDoc chứa id tài liệu và điểm số của nó
ScoreDoc[] ketQuaTimKiem = topDocs.scoreDocs;
for (ScoreDoc ketQua : ketQuaTimKiem) {
System.out.println("= = = = = = = = = = = = = = = = = = =");
// Lấy id tài liệu và điểm số
int idTaiLieu = ketQua.doc;
float diemSoTaiLieu = ketQua.score;
System.out.println("ID tài liệu= " + idTaiLieu + " , Điểm số= " + diemSoTaiLieu);
// Lấy dữ liệu tài liệu theo ID tài liệu -- tương đương truy vấn dữ liệu theo khóa chính trong cơ sở dữ liệu quan hệ
Document taiLieu = timKiemChiMuc.doc(idTaiLieu);
System.out.println("ID sách: " + taiLieu.get("bookId"));
// Hiển thị nổi bật tên sách
String tenSach = taiLieu.get("bookName");
if(tenSach != null) {
// 5. Sử dụng lớp TokenSources để lấy đối tượng luồng (TokenStream)
// getTokenStream: lấy đối tượng luồng của tài liệu hiện tại
// Tham số 1: đối tượng tài liệu hiện tại
// Tham số 2: tên trường cần hiển thị nổi bật
// Tham số 3: đối tượng phân tích
TokenStream luongTu = TokenSources.getTokenStream(taiLieu, "bookName", phanTich);
// 6. Sử dụng đối tượng thành phần hiển thị nổi bật để hoàn thành hiển thị nổi bật
// getBestFragment: lấy nội dung kết quả hiển thị nổi bật
// Tham số 1: đối tượng luồng của tài liệu hiện tại
// Tham số 2: nội dung mục tiêu cần hiển thị nổi bật
tenSach = thanhPhanNenSang.getBestFragment(luongTu, tenSach);
}
System.out.println("Tên sách: " + tenSach);
System.out.println("Giá sách: " + taiLieu.get("bookPrice"));
System.out.println("Ảnh sách: " + taiLieu.get("bookPic"));
System.out.println("Mô tả sách: " + taiLieu.get("bookDesc"));
}
// 8. Đóng tài nguyên
docDoc.close();
}
/**
* Kiểm tra hiển thị nổi bật - Yêu cầu: Hiển thị nổi bật tên sách trong kết quả tìm kiếm (từ khóa là java)
* @throws Exception
*/
@Test
public void kiemTraNenSang() throws Exception {
//1. Tạo đối tượng truy vấn
TermQuery truyVanTu = new TermQuery(new Term("bookName","java"));
// 2. Thực thi tìm kiếm với hiển thị nổi bật
this.timKiemVaNenSang(truyVanTu);
}
2.3 Tùy chỉnh thẻ HTML để hiển thị nổi bật
Câu hỏi: Trong dự án thực tế, làm thế nào để sử dụng các thẻ HTML tùy chỉnh để hiển thị nổi bật kết quả tìm kiếm?
- Tạo đối tượng định dạng thẻ HTML (SimpleHTMLFormatter)
- Tạo đối tượng thành phần hiển thị nổi bật (Highlighter), chỉ định sử dụng đối tượng SimpleHTMLFormatter
// Thêm xử lý hiển thị nổi bật ============================== bắt đầu
// 1. Tạo đối tượng điểm số (QueryScorer), dùng để đánh điểm cho nội dung hiển thị nổi bật
QueryScorer diemSo = new QueryScorer(query);
// 2. Tạo đối tượng phân đoạn (Fragmenter), dùng để cắt nội dung hiển thị nổi bật
Fragmenter phanDoan = new SimpleSpanFragmenter(diemSo);
// 3. Tạo đối tượng thành phần hiển thị nổi bật (Highlighter), thực thi hiển thị nổi bật
// 3.1. Thực thi hiển thị nổi bật kết quả tìm kiếm bằng thẻ HTML tùy chỉnh
// 1) Tạo đối tượng định dạng thẻ HTML cho hiển thị nổi bật (SimpleHTMLFormatter)
// preTag: chỉ định phần bắt đầu của thẻ HTML (<font color='red'>)
// postTag: chỉ định phần kết thúc của thẻ HTML (</font>)
SimpleHTMLFormatter dinhDang = new SimpleHTMLFormatter("<font color='red'>", "</font>");
// 2) Chỉ định đối tượng thành phần hiển thị nổi bật (Highlighter), sử dụng đối tượng SimpleHTMLFormatter
Highlighter thanhPhanNenSang = new Highlighter(dinhDang, diemSo);
// Đặt đối tượng phân đoạn
thanhPhanNenSang.setTextFragmenter(phanDoan);
// 4. Tạo đối tượng phân tích (Analyzer), dùng để tách từ
Analyzer phanTich = new IKAnalyzer();
// Thêm xử lý hiển thị nổi bật ============================== kết thúc