摘要:全文檢索概述數據分類結構化數據具有固定格式或者長度有限的數據,例如數據庫中的表。語句非結構化數據與結構化數據對立,例如郵件網頁文檔。
全文檢索概述 數據分類
結構化數據:具有固定格式或者長度有限的數據,例如數據庫中的表。【SQL語句】
非結構化數據:與結構化數據對立,例如:郵件、網頁、word文檔。【數據掃描、全文檢索】
半結構化數據:介于兩者之間,例如xml或者json格式的數據。
全文檢索過程反向索引(倒排表):由字符串到文件的映射是文件到字符串映射的反向過程。
索引創建 索引檢索 Lucene數學模型 文檔、域、詞元文檔是Lucene搜索和索引的原子單位,文檔為包含一個或者多個域的容器,而域則是依次包含“真正的”被搜索的內容,域值通過分詞技術處理,得到多個詞元。
For Example,一篇小說(斗破蒼穹)信息可以稱為一個文檔,小說信息又包含多個域,例如:標題(斗破蒼穹)、作者、簡介、最后更新時間等等,對標題這個域采用分詞技術又可以得到一個或者多個詞元(斗、破、蒼、穹)。
詞元權重計算Term Frequency(tf):此term在文檔中出現的次數,tf越大則該詞元越重要。
Document Frequency(df):有多少文檔包含此term,df越大該詞元越不重要。
空間向量模型如下:
計算夾角的余弦值,夾角越小,余弦值越大,分值越大,從而相關性越大。
Lucene文件結構 層次結構index:一個索引存放在一個目錄中;
segment:一個索引中可以有多個段,段與段之間是獨立的,添加新的文檔可能產生新段,不同的段可以合并成一個新段;
document:文檔是創建索引的基本單位,不同的文檔保存在不同的段中,一個段可以包含多個文檔;
field:域,一個文檔包含不同類型的信息,可以拆分開索引;
term:詞,索引的最小單位,是經過詞法分析和語言處理后的數據。
正向信息按照層次依次保存了從索引到詞的包含關系:index-->segment-->document-->field-->term。
反向信息反向信息保存了詞典的倒排表映射:term-->document
配置Lucene開發環境Lucene是ASF的開源項目,最新版本是5.2.1,但是鑒于網絡上大多數教程使用的是Lucene 4,在本文中使用的版本是Lucene 4.3.1,下載解壓,到對應目錄找到以下的jar包并添加到構建路徑中。
如果使用maven其maven依賴如下:
Lucene常用功能介紹 索引創建 創建索的關鍵類org.apache.lucene lucene-core 4.3.1 org.apache.lucene lucene-queryparser 4.3.1 org.apache.lucene lucene-queries 4.3.1 org.apache.lucene lucene-highlighter 4.3.1 org.apache.lucene lucene-analyzers-smartcn 4.3.1 org.apache.lucene lucene-analyzers-common 4.3.1
創建索引的示例代碼:
/** * 索引創建 */ @Test public void createIndex() { // 創建一個分詞器(指定Lucene版本) Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_43); // IndexWriter配置信息(指定Lucene版本和分詞器) IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_43, analyzer); // 設置索引的打開方式 indexWriterConfig.setOpenMode(OpenMode.CREATE_OR_APPEND); // 創建Directory對象和IndexWriter對象 Directory directory = null; IndexWriter indexWriter = null; try { directory = FSDirectory.open(new File("Lucene_index/test")); // 檢查Directory對象是否處于鎖定狀態(如果鎖定則進行解鎖) if (IndexWriter.isLocked(directory)) { IndexWriter.unlock(directory); } indexWriter = new IndexWriter(directory, indexWriterConfig); } catch (IOException e) { e.printStackTrace(); } // 創建測試文檔并為其添加域 Document doc1 = new Document(); doc1.add(new StringField("id", "abcde", Store.YES)); // 添加一個id域,域值為abcde doc1.add(new TextField("content", "使用Lucene實現全文檢索", Store.YES)); // 文本域 doc1.add(new IntField("num", 1, Store.YES)); // 添加數值域 // 將文檔寫入索引 try { indexWriter.addDocument(doc1); } catch (IOException e) { e.printStackTrace(); } Document doc2 = new Document(); doc2.add(new StringField("id", "yes", Store.YES)); doc2.add(new TextField("content", "Docker容器技術簡介", Store.YES)); doc2.add(new IntField("num", 2, Store.YES)); try { indexWriter.addDocument(doc2); } catch (IOException e) { e.printStackTrace(); } // 將IndexWriter提交 try { indexWriter.commit(); } catch (IOException e) { e.printStackTrace(); } finally{ try { indexWriter.close(); directory.close(); } catch (IOException e) { e.printStackTrace(); } } }
生成的索引文件如下:
索引檢索 索引檢索關鍵類利用以下的檢索程序對前面創建的索引進行檢索:
/** * 索引檢索 */ @Test public void searchIndex(){ Directory directory = null; DirectoryReader dReader = null; try { directory = FSDirectory.open(new File("Lucene_index/test")); // 索引文件 dReader = DirectoryReader.open(directory); // 讀取索引文件 IndexSearcher searcher = new IndexSearcher(dReader); // 創建IndexSearcher對象 Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_43); // 指定分詞技術(標準分詞-與創建索引時使用的分詞技術一致) // 創建查詢字符串(指定搜索域和采用的分詞技術) QueryParser parser = new QueryParser(Version.LUCENE_43, "content", analyzer); Query query = parser.parse("Docker"); // 創建Query對象(指定搜索詞) // 檢索索引(指定前10條) TopDocs topDocs = searcher.search(query, 10); if (topDocs != null) { System.out.println("符合條件的文檔總數為:" + topDocs.totalHits); for (int i = 0; i < topDocs.scoreDocs.length; i++) { Document doc = searcher.doc(topDocs.scoreDocs[i].doc); System.out.println("id = " + doc.get("id") + ",content = " + doc.get("content") + ",num = " + doc.get("num")); } } } catch (IOException e) { e.printStackTrace(); } catch (ParseException e) { e.printStackTrace(); } finally{ try { dReader.close(); directory.close(); } catch (IOException e) { e.printStackTrace(); } } }
運行結果:
Lucene分詞器 常見分詞器其中IKAnalyzer需要下載專門的jar包
/** * 常見分詞器 */ @Test public void testAnalyzer(){ final String str = "利用Lucene 實現全文檢索"; Analyzer analyzer = null; analyzer = new StandardAnalyzer(Version.LUCENE_43); // 標準分詞 print(analyzer, str); analyzer = new IKAnalyzer(); // 第三方中文分詞 print(analyzer, str); analyzer = new WhitespaceAnalyzer(Version.LUCENE_43); // 空格分詞 print(analyzer, str); analyzer = new SimpleAnalyzer(Version.LUCENE_43); // 簡單分詞 print(analyzer, str); analyzer = new CJKAnalyzer(Version.LUCENE_43); // 二分法分詞 print(analyzer, str); analyzer = new KeywordAnalyzer(); // 關鍵字分詞 print(analyzer, str); analyzer = new StopAnalyzer(Version.LUCENE_43); //被忽略詞分詞器 print(analyzer, str); } /** * 該方法用于打印分詞器及其分詞結果 * @param analyzer 分詞器 * @param str 需要分詞的字符串 */ public void print(Analyzer analyzer,String str){ StringReader stringReader = new StringReader(str); try { TokenStream tokenStream = analyzer.tokenStream("", stringReader); // 分詞 tokenStream.reset(); CharTermAttribute term = tokenStream.getAttribute(CharTermAttribute.class); // 獲取分詞結果的CharTermAttribute System.out.println("分詞技術:" + analyzer.getClass()); while (tokenStream.incrementToken()) { System.out.print(term.toString() + "|"); } System.out.println(); } catch (IOException e) { e.printStackTrace(); } }
運行結果:
Query創建/** * 創建Query */ @Test public void createQuery(){ String key = "JAVA EE Lucene案例開發"; String field = "name"; String[] fields = {"name","content"}; Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_43); // 分詞器 // 單域查詢 QueryParser parser1 = new QueryParser(Version.LUCENE_43, field, analyzer); Query query1 = null; try { query1 = parser1.parse(key); // 使用QueryParser創建Query } catch (ParseException e) { e.printStackTrace(); } System.out.println(QueryParser.class + query1.toString()); // 多域查詢 MultiFieldQueryParser parser2 = new MultiFieldQueryParser(Version.LUCENE_43, fields, analyzer); try { query1 = parser2.parse(key); } catch (ParseException e) { e.printStackTrace(); } System.out.println(QueryParser.class + query1.toString()); // 短語查詢 query1 = new TermQuery(new Term(field, key)); System.out.println(TermQuery.class + query1.toString()); // 前綴查詢 query1 = new PrefixQuery(new Term(field, key)); System.out.println(PrefixQuery.class + query1.toString()); // 短語查詢 PhraseQuery query2 = new PhraseQuery(); query2.setSlop(2); // 設置短語間的最大距離是2 query2.add(new Term(field, "Lucene")); query2.add(new Term(field, "案例")); System.out.println(PhraseQuery.class + query2.toString()); // 通配符查詢 query1 = new WildcardQuery(new Term(field, "Lucene?")); System.out.println(WildcardQuery.class + query1.toString()); // 字符串范圍搜索 query1 = TermRangeQuery.newStringRange(field, "abc", "azz", false, false); System.out.println(TermRangeQuery.class + query1.toString()); // 布爾條件查詢 BooleanQuery query3 = new BooleanQuery(); query3.add(new TermQuery(new Term(field, "Lucene")),Occur.SHOULD); // 添加條件 query3.add(new TermQuery(new Term(field, "案例")),Occur.MUST); query3.add(new TermQuery(new Term(field, "案例")),Occur.MUST_NOT); System.out.println(BooleanQuery.class + query3.toString()); }
運行結果:
IndexSearcher常用方法檢索關鍵類
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/64432.html
閱讀 2738·2021-10-11 10:57
閱讀 1569·2021-09-26 09:55
閱讀 1310·2021-09-06 15:11
閱讀 3447·2021-08-26 14:16
閱讀 662·2019-08-30 15:54
閱讀 535·2019-08-30 12:43
閱讀 3290·2019-08-29 16:18
閱讀 2565·2019-08-23 16:14