lucene框架全文檢索搜尋引擎方案
搜尋引擎技術方案
- 搜尋引擎方案
- 功能需求背景:
----有搜尋引擎需求
- 功能需求
- 提高查詢效率,關鍵詞全文檢索。
- 不需要訪問多次資料庫,只能一次資料庫查詢。
- 準確關鍵詞全文檢索。
- 由於查詢功能效率較差,等待時間過長,資料量大以及多租戶多使用者關係查詢。
- 需求分析
- 提高使用者體驗,查詢效率,關鍵詞全文檢索。
- 準確性查詢關鍵詞全文檢索資料,不使用模糊查詢。
- 多租戶與使用者關係:多對多,多對一,一對多。
- 根據多租戶與使用者關係來關鍵詞全文檢索。
- 解決方案(建議使用lucene框架搜尋引擎)
方案一:(推薦)
- 第一步:定義一個租戶標識作為索引庫(即伺服器碟符資料夾路徑)。
- 第二步:dataId+使用者標識=idField(索引庫id)。
- 第三步:指定檢索欄位拼接於nameField(索引庫name)
- 第四步:對索引庫增刪改。
- 第五步:全文檢索出該租戶下所有符合的關鍵詞檢索(可以設定檢索的前幾條)。
- 第六步:通過使用者標識過濾使用者資料,從idField(索引庫id)解析dataId儲存資料集。
- 第七步:通過dataId資料集去資料庫查詢對應資料(id查詢結果集)。
- 第八步:查詢結果集返回頁面查詢。
方案二:
- 第一步:定義一個索引庫(即伺服器碟符資料夾路徑)。
- 第二步:租戶標識+dataId+使用者標識=idField(索引庫id)。
- 第三步:指定檢索欄位拼接於nameField(索引庫name)
- 第四步:對索引庫增刪改。
- 第五步:全文檢索出該租戶下所有符合的關鍵詞檢索(可以設定檢索的前幾條)。
- 第六步:通過租戶標識過濾租戶資料,通過使用者標識過濾使用者資料,從idField(索引庫id)解析dataId儲存資料集。
- 第七步:通過dataId資料集去資料庫查詢對應資料(id查詢結果集)。
- 第八步:查詢結果集返回頁面查詢。
- Lucene索引結構圖解
- Lucene全文檢索說明
- 索引庫的增、刪、改是由indexWriter來操作的
- 同一個時刻內。同一個索引庫,僅僅能同意一個indexWriter操作
- 當IndexWriter建立完畢以後,indexwriter所指向的索引庫就被佔據了。僅僅有當indexWriter.close時。才幹釋放鎖的資源
- 當一個新的indexWriter想擁有索引庫時,原來的indexWriter必須釋放鎖
- 僅僅要索引庫中存在write.lock檔案,說明上鎖了
- indexWriter.close有兩層含義:1. 關閉IO資源; 2.釋放鎖
- 能夠設定非常多個索引庫.
- 索引庫能不能合併起來?
假設是記憶體索引庫
Directory ramDirectory = new RamDirectory(Directory d);
這樣就能夠把一個索引庫放入到記憶體索引庫中
利用IndexWriter.addIndexesNoOptimize方法能夠把非常多個索引庫進行合併操作.
- 應用程式能不能在記憶體中和索引庫進行互動.
- 搜尋引擎實現
- 索引庫寫入資訊
public void testCreateIndex() throws Exception{
/**
* 1、建立一個student物件,而且把資訊存放進去
* 2、呼叫indexWriter的API把資料存放在索引庫中
* 3、關閉indexWriter
*/
// 建立一個Student物件。而且把資訊存放進去
Student student = new Student();
student.setId(1L);
student.setName("張三");
// 呼叫indexWriter的API把資料存放在索引庫中
/**
* 建立一個IndexWriter
* 引數三個 1、索引庫, 指向索引庫的位置 2、分詞器
*/
// 建立索引庫
Directory directory = FSDirectory.open(new File("./indexDir"));
// 建立分詞器
Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_30);
IndexWriter indexWriter = new IndexWriter(directory, analyzer, MaxFieldLength.LIMITED);
// 把一個student物件轉化成document
Document document = new Document();
Field idField = new Field("id",student.getId().toString(),Store.YES,Index.NOT_ANALYZED);
Field nameField = new Field("name",student.getName(),Store.YES,Index.ANALYZED);
document.add(idField);
document.add(nameField);
indexWriter.addDocument(document);
// 關閉indexWriter
indexWriter.close();
}
- 索引庫讀取資訊
public void testSearchIndex() throws Exception{
/**
* 1、建立一個IndexSearch物件
* 2、呼叫search方法進行檢索
* 3、輸出內容
*/
// 建立一個 IndexSearch物件
Directory directory = FSDirectory.open(new File("./indexDir"));
IndexSearcher indexSearcher = new IndexSearcher(directory);
// 呼叫search方法進行檢索
Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_30);
QueryParser queryParser = new QueryParser(Version.LUCENE_30,"name",analyzer);
Query query = queryParser.parse("張"); // 要查詢的關鍵詞
TopDocs topDocs = indexSearcher.search(query, 2); // 前兩條
int count = topDocs.totalHits; // 依據關鍵詞查詢出來的總的記錄數
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
List<Student> studentList = new ArrayList<Student>();
for(ScoreDoc scoreDoc:scoreDocs){
float score = scoreDoc.score; // 關鍵詞得分
int index = scoreDoc.doc; // 索引的下標
Document document = indexSearcher.doc(index);
// 把document轉化成Student
Student student = new Student();
student.setId(Long.parseLong(document.get("id"))); // document.getField("id").stringValue()
student.setTitle(document.get("name"));
studentList.add(student);
}
for(Student student:studentList){
System.out.println(student.getId());
System.out.println(student.getName());
}
}