zoukankan      html  css  js  c++  java
  • 使用Lucene.NET实现简单的站内搜索

    使用Lucene.NET实现简单的站内搜索

    1. 导入Lucene.NET 开发包

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

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

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

    3. 搜索,根据索引查找

        1 using System;
        2 using Lucene.Net.Store;
        3 using Lucene.Net.Index;
        4 using Lucene.Net.Analysis.PanGu;
        5 using Lucene.Net.Documents;
        6 
        7 namespace BLL
        8 {
        9     class IndexHelper
       10     {
       11         /// <summary>
       12         /// 日志小助手
       13         /// </summary>
       14         static Common.LogHelper logger = new Common.LogHelper(typeof(SearchBLL));
       15         /// <summary>
       16         /// 索引保存的位置,保存在配置文件中从配置文件读取
       17         /// </summary>
       18         static string indexPath = Common.ConfigurationHelper.AppSettingMapPath("IndexPath");
       19         
       20         /// <summary>
       21         /// 创建索引文件或更新索引文件
       22         /// </summary>
       23         /// <param name="item">索引信息</param>
       24         public static void CreateIndex(Model.HelperModel.IndexFileHelper item)
       25         {
       26             try
       27             {
       28                 //索引存储库
       29                 FSDirectory directory = FSDirectory.Open(new System.IO.DirectoryInfo(indexPath), new NativeFSLockFactory());
       30                 //判断索引是否存在
       31                 bool isUpdate = IndexReader.IndexExists(directory);
       32                 if (isUpdate)
       33                 {
       34                     //如果索引目录被锁定(比如索引过程中程序异常退出),则首先解锁
       35                     if (IndexWriter.IsLocked(directory))
       36                     {
       37                         //解锁索引库
       38                         IndexWriter.Unlock(directory);
       39                     }
       40                 }
       41                 //创建IndexWriter对象,添加索引
       42                 IndexWriter writer = new IndexWriter(directory, new PanGuAnalyzer(), !isUpdate, Lucene.Net.Index.IndexWriter.MaxFieldLength.UNLIMITED);
       43                 //获取新闻 title部分
       44                 string title = item.FileTitle;
       45                 //获取新闻主内容
       46                 string body = item.FileContent;
       47                 //为避免重复索引,所以先删除number=i的记录,再重新添加
       48                 //尤其是更新的话,更是必须要先删除之前的索引
       49                 writer.DeleteDocuments(new Term("id", item.FileName));
       50                 //创建索引文件 Document
       51                 Document document = new Document();
       52                 //只有对需要全文检索的字段才ANALYZED
       53                 //添加id字段
       54                 document.Add(new Field("id", item.FileName, Field.Store.YES, Field.Index.NOT_ANALYZED));
       55                 //添加title字段
       56                 document.Add(new Field("title", title, Field.Store.YES, Field.Index.NOT_ANALYZED));
       57                 //添加body字段
       58                 document.Add(new Field("body", body, Field.Store.YES, Field.Index.ANALYZED, Lucene.Net.Documents.Field.TermVector.WITH_POSITIONS_OFFSETS));
       59                 //添加url字段
       60                 document.Add(new Field("url", item.FilePath, Field.Store.YES, Field.Index.NOT_ANALYZED));
       61                 //写入索引库
       62                 writer.AddDocument(document);
       63                 //关闭资源
       64                 writer.Close();
       65                 //不要忘了Close,否则索引结果搜不到
       66                 directory.Close();
       67                 //记录日志
       68                 logger.Debug(String.Format("索引{0}创建成功",item.FileName));
       69             }
       70             catch (SystemException ex)
       71             {
       72                 //记录错误日志
       73                 logger.Error(ex);
       74                 throw;
       75             }
       76             catch (Exception ex)
       77             {
       78                 //记录错误日志
       79                 logger.Error(ex);
       80                 throw;
       81             }
       82         }
       83 
       84         /// <summary>
       85         /// 根据id删除相应索引
       86         /// </summary>
       87         /// <param name="guid">要删除的索引id</param>
       88         public static void DeleteIndex(string guid)
       89         {
       90             try
       91             {
       92                 ////索引存储库
       93                 FSDirectory directory = FSDirectory.Open(new System.IO.DirectoryInfo(indexPath), new NativeFSLockFactory());
       94                 //判断索引库是否存在索引
       95                 bool isUpdate = IndexReader.IndexExists(directory);
       96                 if (isUpdate)
       97                 {
       98                     //如果索引目录被锁定(比如索引过程中程序异常退出),则首先解锁
       99                     if (IndexWriter.IsLocked(directory))
      100                     {
      101                         IndexWriter.Unlock(directory);
      102                     }
      103                 }
      104                 IndexWriter writer = new IndexWriter(directory, new PanGuAnalyzer(), !isUpdate, Lucene.Net.Index.IndexWriter.MaxFieldLength.UNLIMITED);
      105                 //删除索引文件
      106                 writer.DeleteDocuments(new Term("id", guid));
      107                 writer.Close();
      108                 directory.Close();//不要忘了Close,否则索引结果搜不到
      109                 logger.Debug(String.Format("删除索引{0}成功", guid));
      110             }
      111             catch (Exception ex)
      112             {
      113                 //记录日志
      114                 logger.Error(ex);
      115                 //抛出异常
      116                 throw;
      117             }
      118         }
      119     }
      120 }
      IndexHelper 添加、更新、删除索引
        1 using Lucene.Net.Analysis;
        2 using Lucene.Net.Analysis.PanGu;
        3 using Lucene.Net.Documents;
        4 using Lucene.Net.Index;
        5 using Lucene.Net.Search;
        6 using Lucene.Net.Store;
        7 using Model.HelperModel;
        8 using System;
        9 using System.Collections.Generic;
       10 
       11 namespace BLL
       12 {
       13     public static class SearchBLL
       14     {
       15         //一个类中可能会有多处输出到日志,多处需要记录日志,常将logger做成static 静态变量
       16         /// <summary>
       17         /// 日志助手
       18         /// </summary>
       19         static Common.LogHelper logger = new Common.LogHelper(typeof(SearchBLL));
       20         /// <summary>
       21         /// 索引保存位置
       22         /// </summary>
       23         static string indexPath = Common.ConfigurationHelper.AppSettingMapPath("IndexPath");
       24         /// <summary>
       25         /// 搜索
       26         /// </summary>
       27         /// <param name="keywords">用户搜索的关键词</param>
       28         /// <returns>返回搜索的结果</returns>
       29         public static List<SearchResult> Search(string keywords)
       30         {
       31             try
       32             {
       33                 //索引存储库
       34                 FSDirectory directory = FSDirectory.Open(new System.IO.DirectoryInfo(indexPath), new NoLockFactory());
       35                 //创建IndexReader对象
       36                 IndexReader reader = IndexReader.Open(directory, true);
       37                 //创建IndexSearcher对象
       38                 IndexSearcher searcher = new IndexSearcher(reader);
       39                 //新建PhraseQuery 查询对象
       40                 PhraseQuery query = new PhraseQuery();
       41                 //把用户输入的关键词进行拆词
       42                 foreach (string word in SplitWord(keywords))
       43                 {
       44                     //添加搜索关键词
       45                     query.Add(new Term("body", word));
       46                 }
       47                 //设置分词间距为100字之内
       48                 query.SetSlop(100);
       49                 TopScoreDocCollector collector = TopScoreDocCollector.create(1000, true);
       50                 //根据查询条件查询结果
       51                 searcher.Search(query, null, collector);
       52                 //搜索到的ScoreDoc结果
       53                 ScoreDoc[] docs = collector.TopDocs(0, collector.GetTotalHits()).scoreDocs;
       54                 //保存搜索结果的list
       55                 List<SearchResult> listResult = new List<SearchResult>();
       56                 for (int i = 0; i < docs.Length; i++)
       57                 {
       58                     //取到文档的编号(主键,这个是Lucene .net分配的)
       59                     //检索结果中只有文档的id,如果要取Document,则需要Doc再去取
       60                     //降低内容占用
       61                     int docId = docs[i].doc;
       62                     //根据id找Document
       63                     Document doc = searcher.Doc(docId);
       64                     string number = doc.Get("id");
       65                     string title = doc.Get("title");
       66                     string body = doc.Get("body");
       67                     string url = doc.Get("url");
       68                     //建立一个搜索结果对象
       69                     SearchResult result = new SearchResult();
       70                     result.Number = number;
       71                     result.Title = title;
       72                     result.BodyPreview = Preview(body, keywords);
       73                     result.Url = url;
       74                     //添加到结果列表
       75                     listResult.Add(result);
       76                 }
       77                 if (listResult.Count == 0)
       78                 {
       79                     return null;
       80                 }
       81                 else
       82                 {
       83                     return listResult;
       84                 }
       85             }
       86             catch (SystemException ex)
       87             {
       88                 logger.Error(ex);
       89                 return null;
       90             }
       91             catch (Exception ex)
       92             {
       93                 logger.Error(ex);
       94                 return null;
       95             }
       96         }
       97 
       98         /// <summary>
       99         /// 获取内容预览
      100         /// </summary>
      101         /// <param name="body">内容</param>
      102         /// <param name="keyword">关键词</param>
      103         /// <returns></returns>
      104         private static string Preview(string body, string keyword)
      105         {
      106             //创建HTMLFormatter,参数为高亮单词的前后缀 
      107             PanGu.HighLight.SimpleHTMLFormatter simpleHTMLFormatter = new PanGu.HighLight.SimpleHTMLFormatter("<font color="red">", "</font>");
      108             //创建 Highlighter ,输入HTMLFormatter 和 盘古分词对象Semgent 
      109             PanGu.HighLight.Highlighter highlighter = new PanGu.HighLight.Highlighter(simpleHTMLFormatter, new PanGu.Segment());
      110             //设置每个摘要段的字符数 
      111             highlighter.FragmentSize = 100;
      112             //获取最匹配的摘要段 
      113             string bodyPreview = highlighter.GetBestFragment(keyword, body);
      114             return bodyPreview;
      115         }
      116 
      117         /// <summary>
      118         /// 盘古分词,对用户输入的搜索关键词进行分词
      119         /// </summary>
      120         /// <param name="str">用户输入的关键词</param>
      121         /// <returns>分词之后的结果组成的数组</returns>
      122         private static string[] SplitWord(string str)
      123         {
      124             List<string> list = new List<string>();
      125             Analyzer analyzer = new PanGuAnalyzer();
      126             TokenStream tokenStream = analyzer.TokenStream("", new System.IO.StringReader(str));
      127             Lucene.Net.Analysis.Token token = null;
      128             while ((token = tokenStream.Next()) != null)
      129             {
      130                 list.Add(token.TermText());
      131             }
      132             return list.ToArray();
      133         }
      134     }
      135 }
      Search 通过查找索引实现搜索
       1 namespace Model.HelperModel
       2 {
       3     public class SearchResult
       4     {
       5         public string Number { get; set; }
       6 
       7         public string Title { get; set; }
       8 
       9         public string BodyPreview { get; set; }
      10 
      11         public string Url { get; set; }
      12     }
      13 }
      SearchResult 模型
  • 相关阅读:
    微信浏览器内 h5 直接唤醒 app 之 微信开放标签 wx-open-launch-app
    HTML5之2D物理引擎 Box2D for javascript Games 系列 翻外篇--如何结合createJS应用box2d.js
    HTML5之2D物理引擎 Box2D for javascript Games 系列 第三部分之创建图腾破坏者的关卡
    HTML5之2D物理引擎 Box2D for javascript Games 系列 第二部分
    HTML5之2D物理引擎 Box2D for javascript Games 系列 第一部分
    写给“有钱大爷”、”美工殿下”、“前端文艺青年”的微信HTML5页面设计建议
    微信 JS-SDK Demo “分享信息设置” API 及数字签名生成方法(NodeJS版本)更新时间(2020-10-29)
    NodeJS让前端与后端更友好的分手
    “榕树下·那年”移动app ( hybrid ) 开发总结
    如何在移动端app中应用字体图标icon fonts
  • 原文地址:https://www.cnblogs.com/weihanli/p/webSearchUsingLuceneDotNET.html
Copyright © 2011-2022 走看看