Welcome 微信登录

首页 / 网页编程 / ASP.NET / 使用Lucene.NET实现站内搜索

导入Lucene.NET 开发包

Lucene 是apache软件基金会一个开放源代码的全文检索引擎工具包,是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。Lucene.Net 是 .NET 版的Lucene。

你可以在这里下载到最新的Lucene.NET

创建索引、更新索引、删除索引

搜索,根据索引查找

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>/// 创建索引文件或更新索引文件/// </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);}}//创建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));//创建索引文件 DocumentDocument 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}创建成功",item.FileName));}catch (SystemException ex){//记录错误日志logger.Error(ex);throw;}catch (Exception ex){//记录错误日志logger.Error(ex);throw;}}/// <summary>/// 根据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 通过查找索引实现搜索

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 静态变量/// <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());//创建IndexReader对象IndexReader reader = IndexReader.Open(directory, true);//创建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);//根据查询条件查询结果searcher.Search(query, null, collector);//搜索到的ScoreDoc结果ScoreDoc[] docs = collector.TopDocs(0, collector.GetTotalHits()).scoreDocs;//保存搜索结果的listList<SearchResult> listResult = new List<SearchResult>();for (int i = 0; i < docs.Length; i++){//取到文档的编号(主键,这个是Lucene .net分配的)//检索结果中只有文档的id,如果要取Document,则需要Doc再去取//降低内容占用int docId = docs[i].doc;//根据id找DocumentDocument 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){//创建HTMLFormatter,参数为高亮单词的前后缀 PanGu.HighLight.SimpleHTMLFormatter simpleHTMLFormatter = new PanGu.HighLight.SimpleHTMLFormatter("<font color="red">", "</font>");//创建 Highlighter ,输入HTMLFormatter 和 盘古分词对象Semgent PanGu.HighLight.Highlighter highlighter = new PanGu.HighLight.Highlighter(simpleHTMLFormatter, new PanGu.Segment());//设置每个摘要段的字符数 highlighter.FragmentSize = 100;//获取最匹配的摘要段 string bodyPreview = highlighter.GetBestFragment(keyword, body);return bodyPreview;}/// <summary>/// 盘古分词,对用户输入的搜索关键词进行分词/// </summary>/// <param name="str">用户输入的关键词</param>/// <returns>分词之后的结果组成的数组</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; }}}

以上所述就是本文的全部内容了,希望大家能够喜欢。