温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

利用Lucene.NET怎么实现一个站内搜索功能

发布时间:2020-12-18 15:10:18 来源:亿速云 阅读:228 作者:Leah 栏目:开发技术

利用Lucene.NET怎么实现一个站内搜索功能?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

导入Lucene.NET 开发包

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

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

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

利用Lucene.NET怎么实现一个站内搜索功能

搜索,根据索引查找

利用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));         //创建索引文件 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;       }     }     /// <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;         //保存搜索结果的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;           //根据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)     {       //创建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; }   } }

关于利用Lucene.NET怎么实现一个站内搜索功能问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注亿速云行业资讯频道了解更多相关知识。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI