继夫的玩弄H辣文的小说|女人与拘性猛交视频|精品欧美高清不卡高清|一起做亏亏的事情的视频|啦啦啦在线视频观看|望月直播下载ios版本|国产日韩欧美一区二区三区

Lucene從入門到實戰,一看就會

在了解之前,我們先了解下全文數據查詢 。
全文數據查詢
我們的數據一般分為兩種:結構化數據和非結構化數據
數據庫適合結構化數據的精確查詢,而不適合半結構化、非結構化數據的模糊查詢及靈活搜索(特別是數據量大時),無法提供想要的實時性 。
全文數據查詢順序掃描法
所謂順序掃描,就是要找內容包含一個字符串的文件,就是一個文檔一個文檔的看 。對于每一個文檔,從頭看到尾,如果此文檔包含此字符串,則此文檔為我們要找的文件,接著看下一個文件,直到掃描完所有的文件 。
全文檢索
全文檢索是指計算機索引程序通過掃描文章中的每一個詞 , 對每一個詞建立一個索引,指明該詞在文章中出現的次數和位置,當用戶查詢時,檢索程序就根據事先建立的索引進行查找,并將查找的結果反饋給用戶的檢索方式 。這個過程類似于通過字典中的檢索字表查字的過程 。
全文檢索的基本思路 , 就是將非結構化數據中的一部分信息提取出來,重新組織,使其變得有一定結構 , 然后對這個有一定結構的數據進行搜索,從而達到搜索相對較快的目的 。
這部分從非結構化數據中提取出的然后重新組織的信息,我們稱之索引 , 這種先建立索引數據庫映射文件系統,再對索引進行搜索的過程就叫全文檢索(Full-text )。
具體應用的有單機軟件的搜索(word中的搜索) 站內搜索 ( 京東、 、拉勾職位搜索) 專業搜索引擎公司 (、baidu)的搜索 。
全文檢索通常使用倒排索引來實現 。
3. 正排索引
正排索引是指文檔ID為key,表中記錄每個關鍵字出現的次數位置等,查找時掃描表中的每個文檔中字的信息,直到找到所有包含查詢關鍵字的文檔 。
格式如下:
文檔1的ID > 單詞1:出現次數,出現位置列表;單詞2:出現次數,出現位置列表…………
文檔2的ID > 單詞1:出現次數 , 出現位置列表;單詞2:出現次數,出現位置列表…………
當用戶在主頁上搜索關鍵詞“華為手機”時,假設只存在正向索引( index),那么就需要掃描索引庫中的所有文檔,找出所有包含關鍵詞“華為手機”的文檔,再根據打分模型進行打分,排出名次后呈現給用戶 。因為互聯網上收錄在搜索引擎中的文檔的數目是個天文數字,這樣的索引結構根本無法滿足實時返回排名結果的要求
4. 倒排索引
被用來存儲在全文搜索下某個單詞在一個文檔或一組文檔中的存儲位置的映射 。它是文檔檢索系統中常用的數據結構 。通過倒排索引,可以根據單詞快速獲取包含這個單詞的文檔列表 。
格式如下:
關鍵詞1 > 文檔1的ID :出現次數,出現的位置;文檔2的ID:出現次數 ,出現的位置…………
關鍵詞2 > 文檔1的ID :出現次數 , 出現的位置;文檔2的ID:出現次數 ,出現的位置…………
基礎入門簡介
的作者Doug 是資深的全文索引/檢索專家,最開始發布在他本人的主頁上,2000年開源,2001年10月貢獻給,成為基金的一個子項目 。官網 。現在是開源全文檢索方案的重要選擇 。
是非常優秀的成熟的開源的免費的純java語言的全文索引檢索工具包 。
是一個高性能、可伸縮的信息搜索(IR)庫 。(IR) .它可以為你的應用程序添加索引和搜索能力 。
是為軟件開發人員提供一個簡單易用的工具包,以方便的在目標系統中實現全文檢索的功能 , 或者是以此為基礎建立起完整的全文檢索引擎 。由軟件基金會支持和提供,提供了一個簡單卻強大的應用程序接口,能夠做全文索引和搜索 。是當前以及最近幾年非常受歡迎的免費Java信息檢索程序庫 。
實現的產品
作為一個開放源代碼項目 , 從問世之后 , 引發了開放源代碼社群的巨大反響,程序員們不僅使用它構建具體的全文檢索應用,而且將之集成到各種系統軟件中去,以及構建Web應用,甚至某些商業軟件也采用了作為其內部全文檢索子系統的核心 。
Nutch:頂級開源項目 , 包含網絡爬蟲和搜索引擎(基于)的系統(同 百度、) 。
因它而生 。
Solr : 下的子項目,基于構建的獨立的企業級開源搜索平臺 , 一個服務 。它提供了基于xml/JSON/http的api供外界訪問,還有web管理界面 。
:基于的企業級分布式搜索平臺,它對外提供-web接口,讓程序員可以輕松、方便使用搜索平臺 。
還有大家所熟知的、、、等等都是使用了做搜索框架來實現自己的搜索部分內容,在我們自己的項目中很有必要加入他的搜索能力 , 可以大大提高我們開發系統的搜索體驗度 。
的特性穩定、索引性能高高效、準確、高性能跨平臺模塊構成
是一個用Java寫的高性能、可伸縮的全文檢索引擎工具包,它可以方便的嵌入到各種應用中實現針對應用的全文索引、檢索功能 。的目標是為各種中小型應用程序加入全文檢索功能
應用實戰索引創建流程
第一步:采集一些要索引的原文檔數據
采集數據分類:
1、對于互聯網上網頁,可以使用工具將網頁抓取到本地生成html文件 。
2、數據庫中的數據,可以直接連接數據庫讀取表中的數據 。
3、文件系統中的某個文件數據庫映射文件系統,可以通過I/O操作讀取文件的內容 。
第二步:創建文檔對象 , 進行語法分析,將文檔傳給分詞器()形成一系列詞(Term)
獲取原始內容的目的是為了索引,在索引前需要將原始內容創建成文檔(),文檔中包括一個一個的域(Field),域中存儲內容,再對域中的內容進行分析 , 分析成為一個一個的單詞(Term) 。每個可以有多個Field 。
第三步:索引創建,將得到的詞傳給索引組件()形成倒排索引結構
對所有文檔分析得出的詞匯單元進行索引,索引的目的是為了搜索,最終要實現只搜索被索引的語匯單元從而找到(文檔) 。
創建索引是對語匯單元索引 , 通過詞語找文檔,這種索引的結構叫倒排索引結構 。
第四步:通過索引存儲器 , 將索引寫入到磁盤
Java代碼實現索引創建
引入依賴:
org.apache.lucenelucene-core${lucene-version}org.apache.lucenelucene-queryparser${lucene-version}org.apache.lucenelucene-analyzers-common${lucene-version}commons-iocommons-io2.5
public class TestLuceneIndex {public static void main(String[] args) throws Exception{// 1. 采集數據List bookList = new ArrayList();Book book1=new Book();book1.setId(1);book1.setName("Lucene");book1.setPrice(new BigDecimal("100.45"));book1.setDesc("Lucene Core is a Java library providing powerful indexingn" +"and search features, as well as spellchecking, hit highlighting and advancedn" +"analysis/tokenization capabilities. The PyLucene sub project provides Pythonn" +"bindings for Lucene Core");bookList.add(book1);Book book2=new Book();book2.setId(2);book2.setName("Solr");book2.setPrice(new BigDecimal("66.45"));book2.setDesc("Solr is highly scalable, providing fully fault tolerantn" +"distributed indexing, search and analytics. It exposes Lucene's features throughn" +"easy to use JSON/HTTP interfaces or native clients for Java and other languages");bookList.add(book2);Book book3=new Book();book3.setId(3);book3.setName("Hadoop");book3.setPrice(new BigDecimal("318.33"));book3.setDesc("The Apache Hadoop software library is a framework thatn" +"allows for the distributed processing of large data sets across clusters ofn" +"computers using simple programming models");bookList.add(book3);//2. 創建docment文檔對象List documents = new ArrayList();bookList.forEach(x->{Document document=new Document();document.add(new TextField("id",x.getId().toString(), Field.Store.YES));document.add(new TextField("name",x.getName(), Field.Store.YES));document.add(new TextField("price",x.getPrice().toString(), Field.Store.YES));document.add(new TextField("desc",x.getDesc(), Field.Store.YES));documents.add(document);});//3.創建Analyzer分詞器,對文檔分詞Analyzer analyzer=new StandardAnalyzer();//創建Directory對象 , 聲明索引庫的位置Directory directory=FSDirectory.open(Paths.get("D://lucene/index"));//創建IndexWriteConfig對象 , 寫入索引需要的配置IndexWriterConfig config=new IndexWriterConfig(analyzer);//4.創建IndexWriter對象,添加文檔documentIndexWriter indexWriter=new IndexWriter(directory,config);documents.forEach(doc-> {try {indexWriter.addDocument(doc);} catch (IOException e) {e.printStackTrace();}});//釋放資源indexWriter.close();}}
索引搜索流程用戶輸入查詢語句對查詢語句經過詞法分析和語言分析得到一系列詞(Term)通過語法分析得到一個查詢樹通過索引存儲將索引讀到內存利用查詢樹搜索索引,從而得到每個詞(Term)的文檔列表,對文檔列表進行交、差、并得到結果文檔將搜索到的結果文檔按照對查詢語句的相關性進行排序返回查詢結果給用戶Java代碼實現索引查詢
public class TestLuceneSearch {public static void main(String[] args) throws IOException, ParseException {//1. 創建Query搜索對象Analyzer analyzer=new StandardAnalyzer();//創建搜索解析器QueryParser queryParser=new QueryParser("id",analyzer);Query query=queryParser.parse("desc:data");//2. 創建Directory流對象,聲明索引庫位置Directory directory=FSDirectory.open(Paths.get("D:/lucene/index"));//3. 創建索引讀取對象IndexReaderIndexReader reader=DirectoryReader.open(directory);// 4. 創建索引搜索對象IndexSearcher searcher= new IndexSearcher(reader);//5. 執行搜索 , 指定返回最頂部的10條數據TopDocs topDocs = searcher.search(query, 10);ScoreDoc[] scoreDocs = topDocs.scoreDocs;//6. 解析結果集Stream.of(scoreDocs).forEach(doc->{//獲取文檔Document document = null;try {document = searcher.doc(doc.doc);} catch (IOException e) {e.printStackTrace();}System.out.println(document.get("name"));System.out.println(document.get("id"));});reader.close();}}
Field域Field屬性
存儲對象是以為存儲單元,對象中相關的屬性值則存放到Field中 。Field是文檔中的域,包括Field名和Field值兩部分,一個文檔包括多個Field , Field值即為要索引的內容,也是要搜索的內容 。
Field的三大屬性:
是否做分詞處理 。是:即將Field值進行分詞,分詞的目的是為了索引 。
是否進行索引,將Field分詞后的詞或整個Field值進行索引,索引的目的是為了搜索 。
Field常用類型
Field類型
數據類型
是否分詞
是否索引
是否存儲
說明
(,, Store.YES)
字符串
N
Y
Y/N
字符串類型Field, 不分詞, 作為一個整體進行索引(如: 身份證號, 訂單編號), 是否需要存儲由Store.YES或Store.NO決定
(,, Store.NO)
文本類型
Y
Y
Y/N
文本類型Field,分詞并且索引,是否需要存儲由Store.YES或Store.NO決定
(,, Store.YES) 或( name,int… point)等
數值型代表
Y
Y
Y/N
在 6.0中,替換為,替換為,替換為 , 替換為 。對數值型字段索引,索引不存儲 。要存儲結合即可 。
(,)
支持多種類型
N
N
Y
構建不同類型的Field,不分詞 , 不索引,要存儲
Field代碼應用
public static void main(String[] args) throws IOException {// 1. 采集數據List bookList = Book.buildBookData();List documents=new ArrayList();bookList.forEach(book -> {Document document=new Document();Field id=new IntPoint("id",book.getId());Field id_v=new StoredField("id",book.getId());Field name=new TextField("name",book.getName(),Field.Store.YES);Field price=new FloatPoint("price",book.getPrice().floatValue());Field desc=new TextField("desc",book.getDesc(),Field.Store.NO);document.add(id);document.add(id_v);document.add(name);document.add(price);document.add(desc);documents.add(document);});StandardAnalyzer analyzer = new StandardAnalyzer();Directory directory=FSDirectory.open(Paths.get("D:/lucene/index2"));IndexWriterConfig indexWriterConfig=new IndexWriterConfig(analyzer);IndexWriter indexWriter=new IndexWriter(directory,indexWriterConfig);documents.forEach(doc-> {try {indexWriter.addDocument(doc);} catch (IOException e) {e.printStackTrace();}});indexWriter.close();}
索引維護索引添加
indexWriter.addDocument(document);
索引刪除
根據Term項刪除
indexWriter.deleteDocuments(new Term("name", "solr"));
全部刪除
indexWriter.deleteAll();
更新索引
public static void main(String[] args) throws IOException {Analyzer analyzer=new StandardAnalyzer();Directory directory=FSDirectory.open(Paths.get("d:/lucene/index2"));IndexWriterConfig config=new IndexWriterConfig(analyzer);IndexWriter indexWriter=new IndexWriter(directory,config);Document document=new Document();document.add(new TextField("id","1002", Field.Store.YES));document.add(new TextField("name","修改后", Field.Store.YES));indexWriter.updateDocument(new Term("name","solr"),document);indexWriter.close();}
分詞器分詞器相關概念
分詞器:采集到的數據會存儲到對象的Field域中,分詞器就是將中Field的value的值切分為一個一個的詞 。
停用詞:停用詞是為了節省存儲空間和提高搜索效率,搜索程序在索引頁面或處理搜索請求時回自動忽略某些字或詞,這些字或詞被稱為Stop (停用詞) 。比如語氣助詞、副詞、介詞、連接詞等 。如:“的”、“啊”、“a”、“the”
擴展詞:就是分詞器默認不會切出的詞,但我們希望分詞器切出這樣的詞
借助一些工具,我們可以看到分詞后的結果:
可以看出他將我們的詞“修改后”分為了3個字:“修”、“改”、“后” 。另外英文是按照一個個單詞分的 。
中文分詞器
英文是以單詞為單位的,單詞與單詞之間以空格或逗號分開,所以英文程序是比較好處理的 。
而中文是以字為單位,字又組成詞,字和詞又組成句子 。比如“我愛吃紅薯”,程序不知道“紅薯”是一個詞語還是“吃紅”是一個詞語 。
為了解決這個問題,中文分詞器應運而生
可以看出它把“我愛吃紅薯”分成了很多個符合我們語義的詞語了 。但是里面有一個“吃紅”我們是不需要的 。這種就需要我們自己自定義配置
擴展中文詞庫
如果想配置擴展詞和停用詞,就創建擴展詞的文件和停用詞的文件 。ik給我們提供了自定義配置的擴展,從.cfg.xml配置文件可以看出:
IK Analyzer 擴展配置ext.dic;stopword.dic;
我們新建一個ext.dic , 并配上“吃紅” 。
現在看就沒有“吃紅”這個詞了 。擴展詞典同理 。
注意:不要用自帶的記事本保存擴展詞文件和停用詞文件 , 那樣的話,格式中是含有bom的
搜索
創建查詢的兩種方式 。
1)使用提供的Query子類
2)使用解析查詢表達式
Query子類
詞項查詢,不使用分詞器,精確搜索Field域中的詞 。
public class TestSearch {public static void main(String[] args) throws IOException {Query query=new TermQuery(new Term("name","solr"));doSearch(query);}private static void doSearch(Query query) throws IOException {Directory directory=FSDirectory.open(Paths.get("D:/lucene/index"));IndexReader indexReader=DirectoryReader.open(directory);IndexSearcher searcher=new IndexSearcher(indexReader);TopDocs topDocs = searcher.search(query, 10);System.out.println("查詢到數據的總條數:"+topDocs.totalHits);Stream.of(topDocs.scoreDocs).forEach(doc->{//根據docId查詢文檔Document document = null;try {document = searcher.doc(doc.doc);} catch (IOException e) {e.printStackTrace();}System.out.println(document);});}}
 , 實現組合條件查詢 。
public static void testBooleanQuery() throws IOException {Query query1=new TermQuery(new Term("name","lucene"));Query query2=new TermQuery(new Term("desc","java"));BooleanQuery.Builder builder = new BooleanQuery.Builder();builder.add(query1,BooleanClause.Occur.MUST);builder.add(query2,BooleanClause.Occur.SHOULD);doSearch(builder.build());}
組合關系代表的意思如下:
短語查詢
PhraseQuery phraseQuery = new PhraseQuery("desc","lucene");
兩個短語中間有間隔詞的查詢:
PhraseQuery phraseQuery = new PhraseQuery(3,"desc","lucene","java");
能把類似的句子查出來:
Lucene Core is a Java library providing
和java之間隔了3個詞語
4. 跨度查詢
兩個詞語之間有其他詞語的情況的查詢
public static void testSpanTermQuery() throws IOException {SpanTermQuery tq1 = new SpanTermQuery(new Term("desc", "lucene"));SpanTermQuery tq2 = new SpanTermQuery(new Term("desc", "java"));SpanNearQuery spanNearQuery = new SpanNearQuery(new SpanQuery[] { tq1, tq2},3,true);doSearch(spanNearQuery);}
模糊查詢
:通配符查詢,*代表0或多個字符,?代表1個字符,是轉義符 。通配符查詢會比較慢,不可以通配符開頭(那樣就是所有詞項了)
public static void testWildcardQuery() throws IOException {WildcardQuery wildcardQuery=new WildcardQuery(new Term("name","so*"));doSearch(wildcardQuery);}
:允許查詢中有錯別字
FuzzyQuery fuzzyQuery = new FuzzyQuery(new Term("name", "slors"), 2);
如上面的我把solr打成了slors,也能查詢到 , 上面的參數2代表錯別字能錯多少個,此參數最大為2.
數值查詢
通過 , ,,中的方法構建對應的查詢 。
public static void testPointQuery() throws IOException {Query query = IntPoint.newRangeQuery("id", 1, 4);doSearch(query);}
搜索基礎查詢
查詢語法:
Field域名 +”:”+搜索的關鍵字 。例如: name:java
范圍查詢
Field域名+”:”+[最小值 TO 最大值] 。例如: size:[A TO C]
注意:不支持對數字范圍的搜索,支持的是字符串范圍
組合條件查詢
有兩種寫法:
寫法一:
使用+、減號和不用符號
邏輯
實現
Occur.MUST 查詢條件必須滿足,相當于AND
+(加號)
Occur. 查詢條件可?。?嗟庇贠R
空(不用符號)
Occur. 查詢條件不能滿足,相當于NOT非
-(減號)
示例:
+filename:lucene + content:lucene+filename:lucene content:lucenefilename:lucene content:lucene-filename:lucene content:lucene
寫法二:
使用 AND、OR 、NOT
public static void testQueryParser() throws ParseException, IOException {Analyzer analyzer=new StandardAnalyzer();QueryParser queryParser=new QueryParser("desc",analyzer);Query query = queryParser.parse("desc:java AND name:lucene");doSearch(query);}
r
多個Field的查詢 , 以下查詢等同于:name: desc:
public static void testSearchMultiFieldQuery() throws IOException, ParseException {Analyzer analyzer=new IKAnalyzer();String[] fields={"name","desc"};MultiFieldQueryParser multiFieldQueryParser=new MultiFieldQueryParser(fields,analyzer);Query query = multiFieldQueryParser.parse("lucene");System.out.println(query);doSearch(query);}
public static void testStandardQuery() throws QueryNodeException, IOException {Analyzer analyzer=new StandardAnalyzer();StandardQueryParser parser = new StandardQueryParser(analyzer);Query query = parser.parse("desc:java AND name:lucene", "desc");System.out.println(query);doSearch(query);}
其他查詢:
/通配符匹配 建議通配符在后 通配符在前效率低query = parser.parse("name:L*","desc");query = parser.parse("name:L???","desc");//模糊匹配query = parser.parse("lucene~","desc");//區間查詢query = parser.parse("id:[1 TO 100]","desc");//跨度查詢 ~2表示詞語之間包含兩個詞語query= parser.parse(""lucene java"~2","desc");
【Lucene從入門到實戰,一看就會】本文到此結束,希望對大家有所幫助 。