Hiển thị nổi bật trong Lucene - Cách triển khai bằng Java API

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:

  1. Tạo đối tượng điểm số (QueryScorer) để tính điểm cho nội dung hiển thị nổi bật
  2. Tạo đối tượng phân đoạn (Fragmenter) để cắt nội dung hiển thị nổi bật
  3. Tạo đối tượng thành phần hiển thị nổi bật (Highlighter)
  4. Tạo đối tượng phân tích (Analyzer) để tách từ
  5. Sử dụng lớp TokenSources để lấy đối tượng luồng (TokenStream)
  6. 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?

  1. Tạo đối tượng định dạng thẻ HTML (SimpleHTMLFormatter)
  2. 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

Thẻ: lucene Java search-engine text-highlighting apache-lucene

Đăng vào ngày 1 tháng 6 lúc 23:51