1. 程式人生 > >lucene框架全文檢索搜尋引擎方案

lucene框架全文檢索搜尋引擎方案

搜尋引擎技術方案

  1. 搜尋引擎方案
  • 功能需求背景:

----有搜尋引擎需求

 

  • 功能需求
  1. 提高查詢效率,關鍵詞全文檢索。
  2. 不需要訪問多次資料庫,只能一次資料庫查詢。
  3. 準確關鍵詞全文檢索。
  4. 由於查詢功能效率較差,等待時間過長,資料量大以及多租戶多使用者關係查詢。

 

  • 需求分析
  1. 提高使用者體驗,查詢效率,關鍵詞全文檢索。
  2. 準確性查詢關鍵詞全文檢索資料,不使用模糊查詢。
  3. 多租戶與使用者關係:多對多,多對一,一對多。
  4. 根據多租戶與使用者關係來關鍵詞全文檢索。

 

  • 解決方案(建議使用lucene框架搜尋引擎)

方案一:(推薦)

  1. 第一步:定義一個租戶標識作為索引庫(即伺服器碟符資料夾路徑)。
  2. 第二步:dataId+使用者標識=idField(索引庫id)。
  3. 第三步:指定檢索欄位拼接於nameField(索引庫name)
  4. 第四步:對索引庫增刪改。
  5. 第五步:全文檢索出該租戶下所有符合的關鍵詞檢索(可以設定檢索的前幾條)。
  6. 第六步:通過使用者標識過濾使用者資料,從idField(索引庫id)解析dataId儲存資料集。
  7. 第七步:通過dataId資料集去資料庫查詢對應資料(id查詢結果集)。
  8. 第八步:查詢結果集返回頁面查詢。

 

方案二:

  1. 第一步:定義一個索引庫(即伺服器碟符資料夾路徑)。
  2. 第二步:租戶標識+dataId+使用者標識=idField(索引庫id)。
  3. 第三步:指定檢索欄位拼接於nameField(索引庫name)
  4. 第四步:對索引庫增刪改。
  5. 第五步:全文檢索出該租戶下所有符合的關鍵詞檢索(可以設定檢索的前幾條)。
  6. 第六步:通過租戶標識過濾租戶資料,通過使用者標識過濾使用者資料,從idField(索引庫id)解析dataId儲存資料集。
  7. 第七步:通過dataId資料集去資料庫查詢對應資料(id查詢結果集)。
  8. 第八步:查詢結果集返回頁面查詢。

 

  1. Lucene索引結構圖解

  1. Lucene全文檢索說明
  1. 索引庫的增、刪、改是由indexWriter來操作的
  2. 同一個時刻內。同一個索引庫,僅僅能同意一個indexWriter操作
  3. 當IndexWriter建立完畢以後,indexwriter所指向的索引庫就被佔據了。僅僅有當indexWriter.close時。才幹釋放鎖的資源
  4. 當一個新的indexWriter想擁有索引庫時,原來的indexWriter必須釋放鎖
  5. 僅僅要索引庫中存在write.lock檔案,說明上鎖了
  6. indexWriter.close有兩層含義:1. 關閉IO資源; 2.釋放鎖
  7. 能夠設定非常多個索引庫.
  8. 索引庫能不能合併起來?

        假設是記憶體索引庫

        Directory ramDirectory = new RamDirectory(Directory d);

        這樣就能夠把一個索引庫放入到記憶體索引庫中

        利用IndexWriter.addIndexesNoOptimize方法能夠把非常多個索引庫進行合併操作.

  1. 應用程式能不能在記憶體中和索引庫進行互動.
  1. 搜尋引擎實現
  1. 索引庫寫入資訊

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();

}

  1. 索引庫讀取資訊

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());

}

}