Lucene與搜尋引擎的差別
全文檢索系統是按照全文檢索理論建立起來的用于提供全文檢索服務的軟體系統。
全文檢索系統是一個可以運作的系統,包括建立索引、處理查詢傳回結果集、增加索引、
優化索引結構等功能。例如:百度搜尋、eclipse幫助搜尋、淘寶網商品搜尋。
搜尋引擎是全文檢索技術最主要的一個應用,例如百度。搜尋引擎起源于傳統的資訊全文
檢索理論,即計算機程式通過掃描每一篇文章中的每一個詞,建立以詞為機關的倒排檔案,
檢索程式根據檢索詞在每一篇文章中出現的頻率和每一個檢索詞在一篇文章中出現的機率,
對包含這些檢索詞的文章進行排序,最後輸出排序的結果。全文檢索技術是搜尋引擎的核心支撐技術。
Lucene和搜尋引擎不同,Lucene是一套用java寫的全文檢索的工具包,為應用程式提供了很多個api接口去調用,
可以簡單了解為是一套實作全文檢索的類庫,搜尋引擎是一個全文檢索系統,它是一個單獨運作的軟體。
1、全文檢索,隻檢索文本
2、從資訊源中拷貝到本地并進行加工,稱為索引庫(資訊集合),搜尋時從本地的資訊集合中搜尋
3、文本在建立索引和搜尋時都會分詞。(*都會使用分詞器,并且應使用同一個分詞器)
4、索引庫索引的存放結構:倒排序索引 【索引庫[索引表->][資料集合->存放資料*有文檔内部編号* (首先找分詞器在所有表中存儲)]】
5、索引庫是一組檔案的集合:
(1)Directory 索引庫位置
(2)Document 文檔集合->中有set集合 set<Field> fields;
field的值是文本(如果是其他類型,如數字,日期都要轉成文本) 是鍵值對,鍵是字元串
field name value
f1=new Field("title","XXX");
f2=new Field("body","XXX");
doc.add(f1);
doc.add(f2);
.........
6、HelloWorld程式(索引與搜尋)
(1)添加jar包 核心、分詞器、高亮器
(2)建立索引
(3)搜尋
String filePath="檔案目錄";
String indexPath="索引庫的目錄";//路徑\\兩個反斜線
Analyzer analyzer=new StandarAnalyzer();//分詞器
1、createIndex(){ //建立索引
//File file=new File("磁盤的檔案路徑");//路徑\\兩個反斜線
Document doc=File2DocumentUtils.file2Document(filepath);
//file->doc
//操作索引庫(曾删改索引庫)IndexWriter
IndexWriter indexwriter=new IndexWriter(indexPath{索引目錄},analyzer,true,new MaxFieldLength(10000){MaxFieldLength.LLMITED 整形的最大值});//true 代表每次都建立,對前10000個詞進行索引
indexWriter.addDocment(doc);//增加索引
indexWriter.close();//釋放資源
}
// IndexSearcher 是用來在索引庫中進行查詢的
2、search(){//搜尋
String queryStrng="document";
// 1、把要搜尋的文本解析為query對象
QueryParser queryParser=null;
Query query=queryParser.parse(queryString);
//2、進行查詢
IndexSearcher indexSearcher=null;
Filter filter=null;
//得到的topDocs總結果數
TopDocs topDocs= indexSearcher.search(query,filter,10000);
//3、列印結果 scoreDoc 放的文檔編号
for( ScoreDoc scoreDoc: topDocs.scoreDocs){
int docSn=scoreDoc.doc;//文檔内部編号
Document doc= indexSearcher.doc(docSh);//根據文檔編号取出相應文檔
//擷取name屬性的值
doc.get("name");
}
3、工具類
File2DocumentUtils
//檔案 filename content path size
public static Document fileDocument(String path){
File file=new File(path);
Document doc=new Document();
doc.add(new Field("name",file.getName(),Store.YES{是否存儲 枚舉},Index.ANALYZED{是否索引}));
doc.add(new Field("content",readFileContent(file),Store.YES{是否存儲 枚舉},Index.ANALYZED{是否索引}));
doc.add(new Field("size",String.valueof(file.length()),Store.YES{是否存儲 枚舉},Index.ANALYZED{是否索引}));
doc.add(new Field("path",file.getAbsolutePath(),Store.YES{是否存儲 枚舉},Index.ANALYZED{是否索引}));
return doc;
}
//讀取檔案内容
public static String readFileContent(File file){
BufferedReader reader=new BufferedEeader(new InputStreamReader(new FileInputStream(file)));
StringBuffer content=new StringBuffer();
for(String line=null;(line=reader.readLine())!=null;){
content.append(line).append("\n");
return content.toString();
是否索引 ---> 進行索引----> {分詞後索引、直接索引(把整個值當成一個關鍵詞,不分詞直接索引)}
7、索引庫的位置
1、建立索引
public void test1()throws Exception{
//Directory dir=FSDirectory.getDirectory(indexpath);//放到磁盤中
Directory dir=new RAMDDirectory();//放到記憶體中
Document doc=File2DocumentUtils.file2Document(filepath);
IndexWriter indexwriter=new IndexWriter(dir,analyzer,new MaxFieldLength(10000){MaxFieldLength.LLMITED 整形的最大值});//沒有true可以建立和使用已經存在的索引
}
public void test2(){
Directory fsDir=FSDirectory.getDirectory(indexpath);
//1、啟動時讀取
Directory ramDir=new RAMDirectory();
//運作程式時操作 ramDir
IndexWriter ramIndexWriter =new IndexWriter(ramDir,analyzer,MaxFieldLength.LIMITED);
//添加Document
Document doc=File2DocumentUtils.file2Document(filepath);
ramIndexWriter.addDocument(doc);
ramIndexWriter.close();//一定要關閉在存儲,因為有緩存,不關閉會導緻索引丢失
//2、退出程式時儲存
IndexWriter fsIndexWriter =new IndexWriter(fsDir,true,analyzer,MaxFieldLength.LIMITED);
fsIndexWriter.addIndexesNoOptimis(new Directory[](ramdir));
fsIndexWriter.commit();
fsIndexWriter.optimize();//優化
fsIndexWriter.close();
}
//優化
public void test3(){
//1、啟動時讀取
// Directory ramDir=new RAMDirectory();
IndexWriter fsIndexWriter =new IndexWriter(ramDir,analyzer,MaxFieldLength.LIMITED);
fsIndexWriter.optimze();//優化是做合并操作
8、分詞器
1、英文分詞器 輸入文本--》關鍵詞切分--》去除停用詞--》形态還原--》轉為小寫
2、中文分詞 單詞分詞 二分法分詞 詞典分詞 詞庫分詞器 MMAnalyzer();
9、關鍵詞高亮
//準備高亮器
ForMatter formatter=new SimpleHTMLFOrMatter("<font color='red'>","</font>");
Score score=new QueryScore(query);
HeighLighter highter=new HeighLighter(formatter,score);
Fragmenter fragmenter=new SimpleFragmeter("1000");//指定摘要字元
//高亮
//傳回高亮後的結果,如果目前屬性之中沒有出現關鍵詞,會傳回null
String hc=heighlighter.getBestFragment(analyzer,“content”,doc.get("content"));
if(hc!=null){
doc.getField("content").setValue(hc);
}else{
String content=doc.get("content");
int endIndex=Math.min(50,content.length());
hc=content.subString(0,endIndex);//截取前50個字元
10、查詢
1、查詢字元串,可以使用查詢文法
2、使用對象 Query
public class QueryTest{
IndexDao indexDao=newIndexDao();
public void test(){
Query query=null;
public void testTermQuery(String queryString,int firstResult,int maxResult){//關鍵詞查詢
Term term=new Term("name","房間");//英文關鍵詞全是小寫字元
Query query=new TermQuery(term);
QueryResult qr=indexDao.search(query,0,100);
for(Document doc:qr.getRecordList()){
File2DocumentUtils.printDocumentInfo(doc);
}
//TermQuery
//RangeQuery
//WidcardQuery
//PhraseQuery
//BooleanQuery
public QueryResult search(String queryString,int firstResult,int max Result){
try{
//1、把要搜尋的文本解析成query
String[] fields={"name","content"};
QueryParser queryParser=new MultiFieldQueryParser(fields,analyzer);
Query query=queryParser.parse(queryString);
return search(query,firstResult,maxResults);
}catch(Exception e){
throw new RuntimeException(e);
}finally{
try{
}catch(IOException e){
e.printStackTrace();
//範圍查詢
public void testRangeQuery(){
Term lowerterm=new Term("size","200");
Term upperterm=new Term("size","500")
Query query=new RangeQuery(lowerTerm,upperTerm,true);//true包含邊界
NumberTools.longToString(lowerTerm,upperTerm,true);
NumberTools
queryAndPrintResult(query);
}
//通配符查詢 ? 代表一個字元 * 代表多個
public void testWidcarQuery(){
Term term=new Term("name","roo?");
Query query=new WidcarQuery(term);
queryAndPrintresult(query);
//短語查詢
public void testParseQuery(){
PhraseQuery phraseQuery=new PhraseQuery();
//phraseQuery.add(new Term("name","笑話",1));//1代表位置
phraseQuery.add(new Term("name","房間"));
phraseQuery.add(new Term("name","紳士"));
phraseQuery.setSlop(5);//指定指定的詞中間隔了幾個詞
}
//boolean 查詢
public void testBooleanQuery(){
BooleanQuery boolQuery=new BooleanQuery();
booleanQuery.add(query1,Occur.MUST);//條件一必須出現
11、查詢結果排序
12、過濾器