使用Lucene.NET實現(xiàn)站內搜索
導入Lucene.NET 開發(fā)包
Lucene 是apache軟件基金會一個開放源代碼的全文檢索引擎工具包,是一個全文檢索引擎的架構,提供了完整的查詢引擎和索引引擎,部分文本分析引擎。Lucene的目的是為軟件開發(fā)人員提供一個簡單易用的工具包,以方便的在目標系統(tǒng)中實現(xiàn)全文檢索的功能,或者是以此為基礎建立起完整的全文檢索引擎。Lucene.Net 是 .NET 版的Lucene。
你可以在這里下載到最新的Lucene.NET
創(chuàng)建索引、更新索引、刪除索引

搜索,根據(jù)索引查找

IndexHelper 添加、更新、刪除索引
using System;
using Lucene.Net.Store;
using Lucene.Net.Index;
using Lucene.Net.Analysis.PanGu;
using Lucene.Net.Documents;
namespace BLL
{
class IndexHelper
{
/// <summary>
/// 日志小助手
/// </summary>
static Common.LogHelper logger = new Common.LogHelper(typeof(SearchBLL));
/// <summary>
/// 索引保存的位置,保存在配置文件中從配置文件讀取
/// </summary>
static string indexPath = Common.ConfigurationHelper.AppSettingMapPath("IndexPath");
/// <summary>
/// 創(chuàng)建索引文件或更新索引文件
/// </summary>
/// <param name="item">索引信息</param>
public static void CreateIndex(Model.HelperModel.IndexFileHelper item)
{
try
{
//索引存儲庫
FSDirectory directory = FSDirectory.Open(new System.IO.DirectoryInfo(indexPath), new NativeFSLockFactory());
//判斷索引是否存在
bool isUpdate = IndexReader.IndexExists(directory);
if (isUpdate)
{
//如果索引目錄被鎖定(比如索引過程中程序異常退出),則首先解鎖
if (IndexWriter.IsLocked(directory))
{
//解鎖索引庫
IndexWriter.Unlock(directory);
}
}
//創(chuàng)建IndexWriter對象,添加索引
IndexWriter writer = new IndexWriter(directory, new PanGuAnalyzer(), !isUpdate, Lucene.Net.Index.IndexWriter.MaxFieldLength.UNLIMITED);
//獲取新聞 title部分
string title = item.FileTitle;
//獲取新聞主內容
string body = item.FileContent;
//為避免重復索引,所以先刪除number=i的記錄,再重新添加
//尤其是更新的話,更是必須要先刪除之前的索引
writer.DeleteDocuments(new Term("id", item.FileName));
//創(chuàng)建索引文件 Document
Document document = new Document();
//只有對需要全文檢索的字段才ANALYZED
//添加id字段
document.Add(new Field("id", item.FileName, Field.Store.YES, Field.Index.NOT_ANALYZED));
//添加title字段
document.Add(new Field("title", title, Field.Store.YES, Field.Index.NOT_ANALYZED));
//添加body字段
document.Add(new Field("body", body, Field.Store.YES, Field.Index.ANALYZED, Lucene.Net.Documents.Field.TermVector.WITH_POSITIONS_OFFSETS));
//添加url字段
document.Add(new Field("url", item.FilePath, Field.Store.YES, Field.Index.NOT_ANALYZED));
//寫入索引庫
writer.AddDocument(document);
//關閉資源
writer.Close();
//不要忘了Close,否則索引結果搜不到
directory.Close();
//記錄日志
logger.Debug(String.Format("索引{0}創(chuàng)建成功",item.FileName));
}
catch (SystemException ex)
{
//記錄錯誤日志
logger.Error(ex);
throw;
}
catch (Exception ex)
{
//記錄錯誤日志
logger.Error(ex);
throw;
}
}
/// <summary>
/// 根據(jù)id刪除相應索引
/// </summary>
/// <param name="guid">要刪除的索引id</param>
public static void DeleteIndex(string guid)
{
try
{
////索引存儲庫
FSDirectory directory = FSDirectory.Open(new System.IO.DirectoryInfo(indexPath), new NativeFSLockFactory());
//判斷索引庫是否存在索引
bool isUpdate = IndexReader.IndexExists(directory);
if (isUpdate)
{
//如果索引目錄被鎖定(比如索引過程中程序異常退出),則首先解鎖
if (IndexWriter.IsLocked(directory))
{
IndexWriter.Unlock(directory);
}
}
IndexWriter writer = new IndexWriter(directory, new PanGuAnalyzer(), !isUpdate, Lucene.Net.Index.IndexWriter.MaxFieldLength.UNLIMITED);
//刪除索引文件
writer.DeleteDocuments(new Term("id", guid));
writer.Close();
directory.Close();//不要忘了Close,否則索引結果搜不到
logger.Debug(String.Format("刪除索引{0}成功", guid));
}
catch (Exception ex)
{
//記錄日志
logger.Error(ex);
//拋出異常
throw;
}
}
}
}
Search 通過查找索引實現(xiàn)搜索
using Lucene.Net.Analysis;
using Lucene.Net.Analysis.PanGu;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.Search;
using Lucene.Net.Store;
using Model.HelperModel;
using System;
using System.Collections.Generic;
namespace BLL
{
public static class SearchBLL
{
//一個類中可能會有多處輸出到日志,多處需要記錄日志,常將logger做成static 靜態(tài)變量
/// <summary>
/// 日志助手
/// </summary>
static Common.LogHelper logger = new Common.LogHelper(typeof(SearchBLL));
/// <summary>
/// 索引保存位置
/// </summary>
static string indexPath = Common.ConfigurationHelper.AppSettingMapPath("IndexPath");
/// <summary>
/// 搜索
/// </summary>
/// <param name="keywords">用戶搜索的關鍵詞</param>
/// <returns>返回搜索的結果</returns>
public static List<SearchResult> Search(string keywords)
{
try
{
//索引存儲庫
FSDirectory directory = FSDirectory.Open(new System.IO.DirectoryInfo(indexPath), new NoLockFactory());
//創(chuàng)建IndexReader對象
IndexReader reader = IndexReader.Open(directory, true);
//創(chuàng)建IndexSearcher對象
IndexSearcher searcher = new IndexSearcher(reader);
//新建PhraseQuery 查詢對象
PhraseQuery query = new PhraseQuery();
//把用戶輸入的關鍵詞進行拆詞
foreach (string word in SplitWord(keywords))
{
//添加搜索關鍵詞
query.Add(new Term("body", word));
}
//設置分詞間距為100字之內
query.SetSlop(100);
TopScoreDocCollector collector = TopScoreDocCollector.create(1000, true);
//根據(jù)查詢條件查詢結果
searcher.Search(query, null, collector);
//搜索到的ScoreDoc結果
ScoreDoc[] docs = collector.TopDocs(0, collector.GetTotalHits()).scoreDocs;
//保存搜索結果的list
List<SearchResult> listResult = new List<SearchResult>();
for (int i = 0; i < docs.Length; i++)
{
//取到文檔的編號(主鍵,這個是Lucene .net分配的)
//檢索結果中只有文檔的id,如果要取Document,則需要Doc再去取
//降低內容占用
int docId = docs[i].doc;
//根據(jù)id找Document
Document doc = searcher.Doc(docId);
string number = doc.Get("id");
string title = doc.Get("title");
string body = doc.Get("body");
string url = doc.Get("url");
//建立一個搜索結果對象
SearchResult result = new SearchResult();
result.Number = number;
result.Title = title;
result.BodyPreview = Preview(body, keywords);
result.Url = url;
//添加到結果列表
listResult.Add(result);
}
if (listResult.Count == 0)
{
return null;
}
else
{
return listResult;
}
}
catch (SystemException ex)
{
logger.Error(ex);
return null;
}
catch (Exception ex)
{
logger.Error(ex);
return null;
}
}
/// <summary>
/// 獲取內容預覽
/// </summary>
/// <param name="body">內容</param>
/// <param name="keyword">關鍵詞</param>
/// <returns></returns>
private static string Preview(string body, string keyword)
{
//創(chuàng)建HTMLFormatter,參數(shù)為高亮單詞的前后綴
PanGu.HighLight.SimpleHTMLFormatter simpleHTMLFormatter = new PanGu.HighLight.SimpleHTMLFormatter("<font color=\"red\">", "</font>");
//創(chuàng)建 Highlighter ,輸入HTMLFormatter 和 盤古分詞對象Semgent
PanGu.HighLight.Highlighter highlighter = new PanGu.HighLight.Highlighter(simpleHTMLFormatter, new PanGu.Segment());
//設置每個摘要段的字符數(shù)
highlighter.FragmentSize = 100;
//獲取最匹配的摘要段
string bodyPreview = highlighter.GetBestFragment(keyword, body);
return bodyPreview;
}
/// <summary>
/// 盤古分詞,對用戶輸入的搜索關鍵詞進行分詞
/// </summary>
/// <param name="str">用戶輸入的關鍵詞</param>
/// <returns>分詞之后的結果組成的數(shù)組</returns>
private static string[] SplitWord(string str)
{
List<string> list = new List<string>();
Analyzer analyzer = new PanGuAnalyzer();
TokenStream tokenStream = analyzer.TokenStream("", new System.IO.StringReader(str));
Lucene.Net.Analysis.Token token = null;
while ((token = tokenStream.Next()) != null)
{
list.Add(token.TermText());
}
return list.ToArray();
}
}
}
SearchResult 模型
namespace Model.HelperModel
{
public class SearchResult
{
public string Number { get; set; }
public string Title { get; set; }
public string BodyPreview { get; set; }
public string Url { get; set; }
}
}
以上所述就是本文的全部內容了,希望大家能夠喜歡。
相關文章
ASP.NET 使用application與session對象寫的簡單聊天室程序
寫了快一年的asp.net,application對象還真沒怎么用過??戳丝磿鶕?jù)這兩個對象的特性寫了一個簡單的聊天室程序。真的是非常的簡陋2014-07-07
ASP.NET2.0中用Gridview控件操作數(shù)據(jù)的代碼
在ASP.NET 2.0中,加入了許多新的功能和控件,相比asp.net 1.0/1.1,在各方面都有了很大的提高2012-10-10
ASP.net(C#)從其他網(wǎng)站抓取內容并截取有用信息的實現(xiàn)代碼
ASP.net(C#)從其他網(wǎng)站抓取內容并截取有用信息的實現(xiàn)代碼,需要的朋友可以參考下。2011-09-09
asp.net實現(xiàn)存儲和讀取數(shù)據(jù)庫圖片
這篇文章主要為大家詳細介紹了asp.net實現(xiàn)存儲和讀取數(shù)據(jù)庫圖片,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-11-11
Visual?Studio2022創(chuàng)建WebAPI項目步驟記錄
不管是前后端分離還是提供數(shù)據(jù)服務,WebApi使用的越來越廣泛,而且.NET Core也是我們.NET開發(fā)人員未來發(fā)展的趨勢,所以說學會使用.NET Core Api是非常有必要的,這篇文章主要給大家介紹了關于Visual?Studio2022創(chuàng)建WebAPI項目步驟的相關資料,需要的朋友可以參考下2024-01-01
時間輕松學會.NET Core操作ElasticSearch7的方法
這篇文章主要介紹了時間輕松學會.NET Core操作ElasticSearch7,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-04-04
asp.net 需要登陸的網(wǎng)站上下載網(wǎng)頁源代碼和文件
最近有個項目需要從網(wǎng)絡上下載網(wǎng)頁信息和文件,并且需要登錄后才能下載,所以做了個下載的通用類,供大家參考。2009-05-05

