使用Lucene.NET实现站内搜索

提到Lucene,想必大家都有所耳闻,已经是数年前就出现的开源技术。很多站点都是利用它搭建自己网站的站内搜索。由于最近也在做数据检索方面的东西,也学习了下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 { ///  /// 日志小助手 ///  static Common.LogHelper logger = new Common.LogHelper(typeof(SearchBLL)); ///  /// 索引保存的位置,保存在配置文件中从配置文件读取 ///  static string indexPath = Common.ConfigurationHelper.AppSettingMapPath("IndexPath"); ///  /// 创建索引文件或更新索引文件 ///  /// 索引信息 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)); //创建索引文件 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}创建成功",item.FileName)); } catch (SystemException ex) { //记录错误日志 logger.Error(ex); throw; } catch (Exception ex) { //记录错误日志 logger.Error(ex); throw; } } ///  /// 根据id删除相应索引 ///  /// 要删除的索引id 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 静态变量 ///  /// 日志助手 ///  static Common.LogHelper logger = new Common.LogHelper(typeof(SearchBLL)); ///  /// 索引保存位置 ///  static string indexPath = Common.ConfigurationHelper.AppSettingMapPath("IndexPath"); ///  /// 搜索 ///  /// 用户搜索的关键词 /// 返回搜索的结果 public static List 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; //保存搜索结果的list List listResult = new List(); for (int i = 0; i  /// 获取内容预览 ///  /// 内容 /// 关键词 ///  private static string Preview(string body, string keyword) { //创建HTMLFormatter,参数为高亮单词的前后缀 PanGu.HighLight.SimpleHTMLFormatter simpleHTMLFormatter = new PanGu.HighLight.SimpleHTMLFormatter("", ""); //创建 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; } ///  /// 盘古分词,对用户输入的搜索关键词进行分词 ///  /// 用户输入的关键词 /// 分词之后的结果组成的数组 private static string[] SplitWord(string str) { List list = new List(); 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; } } }

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

以上就是使用Lucene.NET实现站内搜索的详细内容,更多请关注0133技术站其它相关文章!

赞(0) 打赏
未经允许不得转载:0133技术站首页 » ASP编程