2010-11-03 28 views

Trả lời

33

Lucene là một chủ đề khá lớn với rất nhiều các lớp học và phương pháp để trang trải, và bạn thường không thể sử dụng nó mà không hiểu tại ít nhất một số khái niệm cơ bản. Nếu bạn cần một dịch vụ nhanh chóng có sẵn, hãy sử dụng Solr để thay thế. Nếu bạn cần toàn quyền kiểm soát Lucene, hãy tiếp tục đọc. Tôi sẽ trình bày một số khái niệm và lớp học cốt lõi của Lucene, đại diện cho chúng. (Để biết thông tin về cách đọc tệp văn bản trong bộ nhớ, ví dụ: this bài viết).

Bất cứ điều gì bạn sẽ làm trong Lucene - lập chỉ mục hoặc tìm kiếm - bạn cần một máy phân tích. Mục tiêu của phân tích là để tokenize (đột nhập vào từ) và gốc (lấy cơ sở của một từ) văn bản đầu vào của bạn. Nó cũng ném ra những từ thường xuyên nhất như "a", "the", vv Bạn có thể tìm các trình phân tích cho hơn 20 ngôn ngữ hoặc bạn có thể sử dụng SnowballAnalyzer và chuyển ngôn ngữ làm tham số.
Để tạo thể hiện của SnowballAnalyzer cho tiếng Anh bạn này:

Analyzer analyzer = new SnowballAnalyzer(Version.LUCENE_30, "English"); 

Nếu bạn đang đi để văn bản chỉ bằng các ngôn ngữ khác nhau, và muốn chọn phân tích tự động, bạn có thể sử dụng tika's LanguageIdentifier.

Bạn cần lưu trữ chỉ mục của mình ở đâu đó. Có 2 khả năng chính cho việc này: chỉ mục trong bộ nhớ, dễ sử dụng và chỉ mục đĩa, là chỉ mục phổ biến nhất.
Sử dụng bất kỳ của 2 dòng tiếp theo:

Directory directory = new RAMDirectory(); // RAM index storage 
Directory directory = FSDirectory.open(new File("/path/to/index")); // disk index storage 

Khi bạn muốn thêm, cập nhật hoặc xóa tài liệu, bạn cần IndexWriter:

IndexWriter writer = new IndexWriter(directory, analyzer, true, new IndexWriter.MaxFieldLength(25000)); 

Bất kỳ tài liệu (file văn bản trong trường hợp của bạn) là một tập hợp các trường. Để tạo tài liệu, trong đó sẽ tổ chức thông tin về tập tin của bạn, sử dụng này:

Document doc = new Document(); 
String title = nameOfYourFile; 
doc.add(new Field("title", title, Field.Store.YES, Field.Index.ANALYZED)); // adding title field 
String content = contentsOfYourFile; 
doc.add(new Field("content", content, Field.Store.YES, Field.Index.ANALYZED)); // adding content field 
writer.addDocument(doc); // writing new document to the index 

Field constructor mất tên trường, nó là văn bản và ít nhất 2 nhiều tham số. Đầu tiên là một lá cờ, cho thấy Lucene có phải lưu trữ trường này hay không. Nếu nó bằng Field.Store.YES, bạn sẽ có khả năng nhận lại tất cả văn bản của mình từ chỉ mục, nếu không chỉ thông tin chỉ mục về nó sẽ được lưu trữ.
Tham số thứ hai cho biết liệu Lucene có phải lập chỉ mục trường này hay không. Sử dụng Field.Index.ANALYZED cho bất kỳ trường nào bạn sẽ tìm kiếm.
Thông thường, bạn sử dụng cả hai tham số như được hiển thị ở trên.

Đừng quên để đóng IndexWriter của bạn sau khi công việc được thực hiện:

writer.close(); 

Searching là một chút khéo léo. Bạn sẽ cần một số lớp: QueryQueryParser để truy vấn Lucene từ chuỗi, IndexSearcher để tìm kiếm thực tế, TopScoreDocCollector để lưu trữ kết quả (được chuyển đến IndexSearcher làm tham số) và ScoreDoc để lặp qua kết quả. Đoạn tiếp theo cho thấy như thế nào tất cả điều này bao gồm: đối số

IndexSearcher searcher = new IndexSearcher(directory); 
QueryParser parser = new QueryParser(Version.LUCENE_30, "content", analyzer); 
Query query = parser.parse("terms to search"); 
TopScoreDocCollector collector = TopScoreDocCollector.create(HOW_MANY_RESULTS_TO_COLLECT, true); 
searcher.search(query, collector); 

ScoreDoc[] hits = collector.topDocs().scoreDocs; 
// `i` is just a number of document in Lucene. Note, that this number may change after document deletion 
for (int i = 0; i < hits.length; i++) { 
    Document hitDoc = searcher.doc(hits[i].doc); // getting actual document 
    System.out.println("Title: " + hitDoc.get("title")); 
    System.out.println("Content: " + hitDoc.get("content")); 
    System.out.println(); 
} 

Lưu ý thứ hai để các nhà xây dựng QueryParser - đó là lĩnh vực mặc định, ví dụ lĩnh vực đó sẽ được tìm kiếm nếu không có vòng loại đã được đưa ra. Ví dụ: nếu truy vấn của bạn là "title: term", Lucene sẽ tìm kiếm một từ "term" trong trường "title" của tất cả các tài liệu, nhưng nếu truy vấn của bạn chỉ là "term" nếu sẽ tìm kiếm trong trường mặc định, trong trường hợp này - "nội dung". Để biết thêm thông tin, xem Lucene Query Syntax.
QueryParser cũng lấy phân tích làm đối số cuối cùng. Điều này phải được phân tích giống như bạn đã sử dụng để lập chỉ mục văn bản của bạn.

Điều cuối cùng bạn phải biết là thông số đầu tiên TopScoreDocCollector.create. Nó chỉ là một số đại diện cho số lượng kết quả bạn muốn thu thập. Ví dụ, nếu nó bằng 100, Lucene sẽ chỉ thu thập đầu tiên (theo điểm) 100 kết quả và thả phần còn lại. Đây chỉ là hành động tối ưu hóa - bạn thu thập kết quả tốt nhất và nếu bạn không hài lòng với kết quả đó, bạn lặp lại tìm kiếm với số lượng lớn hơn.

Cuối cùng, đừng quên để đóng người tìm kiếm và thư mục để tài nguyên hệ thống không bị lỏng:

searcher.close(); 
directory.close(); 

EDIT: Xem thêm IndexFiles demo class từ Lucene 3.0 sources.

+0

tôi đã thử http://pastebin.com/HqrbBPtp này, nhưng không thành công ... – celsowm

+0

Trong dòng 80 bạn có: 'QueryParser parser = new QueryParser (Version.LUCENE_30," computer ", analyzer);', ie bạn đặt tham số thứ hai (trường mặc định) thành "máy tính" và sau đó bạn tìm kiếm mà không có vòng loại. Lucene cố gắng sử dụng mặc định _field_ "máy tính" để tìm _term_ "máy tính", và vì tài liệu của bạn không có trường như vậy, Lucene không thành công. Sử dụng 'QueryParser parser = new QueryParser (Phiên bản.LUCENE_30," nội dung ", phân tích);' hoặc tìm kiếm với trình định tính: 'Truy vấn truy vấn = parser.parse (" nội dung: máy tính ");'. – ffriend

3
package org.test; 

import java.io.BufferedReader; 
import java.io.File; 
import java.io.FileReader; 
import java.io.IOException; 


import org.apache.lucene.queryParser.*; 
import org.apache.lucene.search.IndexSearcher; 
import org.apache.lucene.search.Query; 
import org.apache.lucene.search.ScoreDoc; 
import org.apache.lucene.search.TopScoreDocCollector; 
import org.apache.lucene.store.Directory; 
import org.apache.lucene.store.FSDirectory; 
import org.apache.lucene.store.LockObtainFailedException; 
import org.apache.lucene.analysis.standard.StandardAnalyzer; 
import org.apache.lucene.index.CorruptIndexException; 
import org.apache.lucene.index.IndexWriter; 
import org.apache.lucene.store.RAMDirectory; 
import org.apache.lucene.util.Version; 
import org.apache.lucene.document.Document; 
import org.apache.lucene.document.Field; 

public class LuceneSimple { 

private static void addDoc(IndexWriter w, String value) throws IOException { 
    Document doc = new Document(); 
    doc.add(new Field("title", value, Field.Store.YES, Field.Index.ANALYZED)); 
    w.addDocument(doc); 
} 



public static void main(String[] args) throws CorruptIndexException, LockObtainFailedException, IOException, ParseException { 

    File dir = new File("F:/tmp/dir"); 

    StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_30); 

    Directory index = new RAMDirectory(); 
    //Directory index = FSDirectory.open(new File("lucDirHello")); 


    IndexWriter w = new IndexWriter(index, analyzer, true, IndexWriter.MaxFieldLength.UNLIMITED); 

    w.setRAMBufferSizeMB(200); 

    System.out.println(index.getClass() + " RamBuff:" + w.getRAMBufferSizeMB()); 

    addDoc(w, "Lucene in Action"); 
    addDoc(w, "Lucene for Dummies"); 
    addDoc(w, "Managing Gigabytes"); 
    addDoc(w, "The Art of Computer Science"); 
    addDoc(w, "Computer Science ! what is that ?"); 


    Long N = 0l; 

    for(File f : dir.listFiles()){ 
     BufferedReader br = new BufferedReader(new FileReader(f)); 
     String line = null; 
     while((line = br.readLine()) != null){ 
     if(line.length() < 140) continue;  
     addDoc(w, line); 
     ++N; 
     } 
     br.close(); 
    } 

    w.close(); 

    // 2. query 
    String querystr = "Computer"; 

    Query q = new QueryParser(Version.LUCENE_30, "title", analyzer).parse(querystr); 


    //search 
    int hitsPerPage = 10; 

    IndexSearcher searcher = new IndexSearcher(index, true); 

    TopScoreDocCollector collector = TopScoreDocCollector.create(hitsPerPage, true); 

    searcher.search(q, collector); 

    ScoreDoc[] hits = collector.topDocs().scoreDocs; 

    System.out.println("Found " + hits.length + " hits."); 
    for(int i=0;i<hits.length;++i) { 
     int docId = hits[i].doc; 
     Document d = searcher.doc(docId); 
     System.out.println((i + 1) + ". " + d.get("title")); 
    } 


    searcher.close(); 

} 

} 
+0

bạn có thể đặt biến "Tệp thư mục" thành thư mục bạn cần lập chỉ mục. – smartnut007

Các vấn đề liên quan