Lucene入門學習

來源:互聯網
上載者:User

標籤:class   opd   except   最簡   ted   二分法   實驗   either   是什麼   

參考部落格: http://blog.csdn.net/ayi_5788/article/category/6348409分頁: http://blog.csdn.net/hu948162999/article/details/41209699 1、 什麼是中文分詞  學過英文的都知道,英文是以單詞為單位的,單詞與單詞之間以空格或者逗號句號隔開。而中文則以字為單位,字又組成詞,字和詞再組成句子。所以對於英文,我們可以簡單以空格判斷某個字串是否為一個單詞,比如I love China,love 和 China很容易被程式區分開來;但中文“我愛中國”就不 一樣了,電腦不知道“中國”是一個詞語還是“愛中”是一個詞語。把中文的句子切分成有意義的詞,就是中文分詞,也稱切詞。我愛中國,分詞的結果是:我 愛 中國。  目前中文分詞還是一個難題———對於需要上下文區別的詞以及新詞(人名、地名等)很難完美的區分。國際上將同樣存在分詞問題的韓國、日本和中國並稱為CJK(Chinese Japanese Korean),對於CJK這個代稱可能包含其他問題,分詞只是其中之一。 2、 中文分詞的實現  Lucene中對中文的處理是基於自動切分的單字切分,或者二元切分。除此之外,還有最大切分(包括向前、向後、以及前後相結合)、最少切分、全切分等等。   Lucene內建了幾個分詞器WhitespaceAnalyzer, SimpleAnalyzer, StopAnalyzer, StandardAnalyzer, ChineseAnalyzer, CJKAnalyzer等。前面三個只適用於英文分詞,StandardAnalyzer對可最簡單地實現中文分詞,即二分法,每個字都作為一個詞,比如:”北京天安門” ==> “北京 京天 天安 安門”。這樣分出來雖然全面,但有很多缺點,比如,索引檔案過大,檢索時速度慢等。ChineseAnalyzer是按字分的,與StandardAnalyzer對中文的分詞沒有大的區別。 CJKAnalyzer是按兩字切分的, 比較武斷,並且會產生垃圾Token,影響索引大小。以上分詞器過於簡單,無法滿足現實的需求,所以我們需要實現自己的分詞演算法。   這樣,在查詢的時候,無論是查詢”北京” 還是查詢”天安門”,將查詢片語按同樣的規則進行切分:”北京”,”天安安門”,多個關鍵詞之間按與”and”的關係組合,同樣能夠正確地映射到相應的索引中。這種方式對於其他亞洲語言:韓文,日文都是通用的。  基於自動切分的最大優點是沒有詞表維護成本,實現簡單,缺點是索引效率低,但對於中小型應用來說,基於2元文法的切分還是夠用的。基於2元切分後的索引一般大小和源檔案差不多,而對於英文,索引檔案一般只有原檔案的30%-40%不同。    目前比較大的搜尋引擎的語言分析演算法一般是基於以上2個機制的結合。關於中文的語言分析演算法,大家可以在Google查關鍵詞”wordsegment search”能找到更多相關的資料。   =============================分割線===============================   由於Lucene不同的版本差距較大,,此系列教程打算把3.5版本,4.5版本,5.0版本都給出個例子,方便大家學習,也方便自己複習。  註:由於Lucene5.0版本是基於JDK1.7開發的,所以想學習的同學請配置1.7及以上的版本。故測試Lucene 6.1.0也適用Lucene 5.0中的代碼。Lucene 6.1.0最低要求也是JDK1.7.  建立索引可分為主要的幾步,我自己實驗過,不同的版本間會有些不同,但是跟著如下的幾大步驟一步一步寫,問題不會太大。   1、建立Directory   2、建立IndexWriter   3、建立Document對象   4、為Document添加Field   5、通過IndexWriter添加文檔到索引中    搜尋可分為如下幾步:   1、建立Directory   2、建立IndexReader   3、根據IndexReader建立IndexSearch   4、建立搜尋的Query   5、根據searcher搜尋並且返回TopDocs   6、根據TopDocs擷取ScoreDoc對象   7、根據searcher和ScoreDoc對象擷取具體的Document對象   8、根據Document對象擷取需要的值    我們向Document添加Field可以有更多的設定,那麼都是什麼意思呢?   name:欄位名,很容易理解   value:欄位值,也很容易理解   store和index怎麼解釋,下面就來看一下這兩個選項的可選值:   Field.Store.YES或者NO(儲存域選項)   設定為YES表示或把這個域中的內容完全儲存到檔案中,方便進行文本的還原   設定為NO表示把這個域的內容不儲存到檔案中,但是可以被索引,此時內容無法完全還原   Field.Index(索引選項)   Index.ANALYZED:進行分詞和索引,適用於標題、內容等   Index.NOT_ANALYZED:進行索引,但是不進行分詞,如果社會安全號碼,姓名,ID等,適用於精確搜尋   Index.ANALYZED_NOT_NORMS:進行分詞但是不儲存norms資訊,這個norms中包括了建立索引的時間和權值等資訊   Index.NOT_ANALYZED_NOT_NORMS:即不進行分詞也不儲存norms資訊   Index.NO:不進行索引    lucene4.5例子:  
import java.io.File;import org.apache.lucene.analysis.Analyzer;import org.apache.lucene.analysis.standard.StandardAnalyzer;import org.apache.lucene.document.Document;import org.apache.lucene.document.Field;import org.apache.lucene.document.FieldType;import org.apache.lucene.document.StringField;import org.apache.lucene.document.TextField;import org.apache.lucene.index.DirectoryReader;import org.apache.lucene.index.IndexWriter;import org.apache.lucene.index.IndexWriterConfig;import org.apache.lucene.queryparser.classic.QueryParser;import org.apache.lucene.search.IndexSearcher;import org.apache.lucene.search.Query;import org.apache.lucene.search.ScoreDoc;import org.apache.lucene.search.TopDocs;import org.apache.lucene.store.Directory;import org.apache.lucene.store.FSDirectory;import org.apache.lucene.util.Version;public class IndexUtil {    private static final String[] ids = { "1", "2", "3" };    private static final String[] authors = { "Darren", "Tony", "Grylls" };    private static final String[] titles = { "Hello World", "Hello Lucene", "Hello Java" };    private static final String[] contents = { "Hello World, I am on my way", "Today is my first day to study Lucene",            "I like Java" };    /**     * 建立索引     */    public static void index() {        IndexWriter indexWriter = null;        try {            // 1、建立Directory            Directory directory = FSDirectory.open(new File("F:/test/lucene/index"));            // 2、建立IndexWriter            Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_45);            IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_45, analyzer);            indexWriter = new IndexWriter(directory, config);            int size = ids.length;            for (int i = 0; i < size; i++) {                // 3、建立Document對象                Document document = new Document();                // 看看四個參數的意思                // 4、為Document添加Field                /**                 * Create field with String value.                 *                  * @param name                 *            field name                 * @param value                 *            string value                 * @param type                 *            field type                 * @throws IllegalArgumentException                 *             if either the name or value is null, or if the field‘s type is neither indexed() nor                 *             stored(), or if indexed() is false but storeTermVectors() is true.                 * @throws NullPointerException                 *             if the type is null                 *                  *             public Field(String name, String value, FieldType type)                 */                /**                 * 注意:這裡與3.5版本不同,原來的建構函式已淘汰                 */                /**                 * 註:這裡4.5版本使用FieldType代替了原來的Store和Index,不同的Field預定義了一些FieldType                 *                  */                // 對ID儲存,但是不分詞也不儲存norms資訊                FieldType idType = TextField.TYPE_STORED;                idType.setIndexed(false);                idType.setOmitNorms(false);                document.add(new Field("id", ids[i], idType));                // 對Author儲存,但是不分詞                FieldType authorType = TextField.TYPE_STORED;                authorType.setIndexed(false);                document.add(new Field("author", authors[i], authorType));                // 對Title儲存,分詞                document.add(new Field("title", titles[i], StringField.TYPE_STORED));                // 對Content不儲存,但是分詞                document.add(new Field("content", contents[i], TextField.TYPE_NOT_STORED));                // 5、通過IndexWriter添加文檔到索引中                indexWriter.addDocument(document);            }        } catch (Exception e) {            e.printStackTrace();        } finally {            try {                if (indexWriter != null) {                    indexWriter.close();                }            } catch (Exception e) {                e.printStackTrace();            }        }    }    /**     * 搜尋     */    public static void search() {        DirectoryReader indexReader = null;        try {            // 1、建立Directory            Directory directory = FSDirectory.open(new File("F:/test/lucene/index"));            // 2、建立IndexReader            /**             * 注意Reader與3.5版本不同:             *              * 所以使用DirectoryReader             *              * @Deprecated public static DirectoryReader open(final Directory directory) throws IOException { return             *             DirectoryReader.open(directory); }             */            indexReader = DirectoryReader.open(directory);            // 3、根據IndexReader建立IndexSearch            IndexSearcher indexSearcher = new IndexSearcher(indexReader);            // 4、建立搜尋的Query            // 使用預設的標準分詞器            Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_45);            // 在content中搜尋Lucene            // 建立parser來確定要搜尋檔案的內容,第二個參數為搜尋的域            QueryParser queryParser = new QueryParser(Version.LUCENE_45, "content", analyzer);            // 建立Query表示搜尋域為content包含Lucene的文檔            Query query = queryParser.parse("Lucene");            // 5、根據searcher搜尋並且返回TopDocs            TopDocs topDocs = indexSearcher.search(query, 10);            // 6、根據TopDocs擷取ScoreDoc對象            ScoreDoc[] scoreDocs = topDocs.scoreDocs;            for (ScoreDoc scoreDoc : scoreDocs) {                // 7、根據searcher和ScoreDoc對象擷取具體的Document對象                Document document = indexSearcher.doc(scoreDoc.doc);                // 8、根據Document對象擷取需要的值                System.out.println("id : " + document.get("id"));                System.out.println("author : " + document.get("author"));                System.out.println("title : " + document.get("title"));                /**                 * 看看content能不能列印出來,為什嗎?                 */                System.out.println("content : " + document.get("content"));            }        } catch (Exception e) {            e.printStackTrace();        } finally {            try {                if (indexReader != null) {                    indexReader.close();                }            } catch (Exception e) {                e.printStackTrace();            }        }    }}

 

Lucene入門學習

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.