使用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 模型

时间: 2024-11-05 18:32:38

使用Lucene.NET实现站内搜索的相关文章

一步步开发自己的博客 .NET版(5、Lucenne.Net 和 必应站内搜索)

前言 这次开发的博客主要功能或特点:    第一:可以兼容各终端,特别是手机端.    第二:到时会用到大量html5,炫啊.    第三:导入博客园的精华文章,并做分类.(不要封我)    第四:做个插件,任何网站上的技术文章都可以转发收藏 到本博客. 所以打算写个系类:<一步步搭建自己的博客> 一步步开发自己的博客  .NET版(1.页面布局.blog迁移.数据加载) 一步步开发自己的博客  .NET版(2.评论功能) 一步步开发自己的博客  .NET版(3.注册登录功能) 一步步开发自己

基于lucene.net 和ICTCLAS2014的站内搜索的实现1

Lucene.net是一个搜索引擎的框架,它自身并不能实现搜索,需要我们自己在其中实现索引的建立,索引的查找.所有这些都是根据它自身提供的API来实现.Lucene.net本身是基于java的,但是经过翻译成.ne版本的,可以在ASP.net中使用这个来实现站内搜索. 要实现基于汉语的搜索引擎,首先的要实现汉语的分词.目前网上大部分都是利用已经有的盘古分词来实现的分词系统,但是盘古分词效果不太好.在这里我把最新的ICTCLAS2014嵌入到Lucene.net中.Lucene.net中所有的分词

基于lucene.net 和ICTCLAS2014的站内搜索的实现2

分词系统建立完毕,这是基础也是核心,后面我们建立索引要用到分词系统. 下面依次讲解索引的建立,索引的查找. 分词系统建立完毕,这是基础也是核心,后面我们建立索引要用到分词系统.下面依次讲解索引的建立,索引的查找. 索引的建立采用的是倒排序,原理就是遍历所有的文本,对其进行分词,然后把分的词汇建立索引表.形式类似如下: 词汇          出现词汇的篇章1,篇章2,篇章3-- 建立索引的时候要注意这样的Document,Field这俩术语.Document代表的是一个文档,它里面包含一个或者多

Lucene.Net 站内搜索

Lucene.Net 站内搜索 一  全文检索: like查询是全表扫描(为性能杀手)Lucene.Net搜索引擎,开源,而sql搜索引擎是收费的Lucene.Net只是一个全文检索开发包(只是帮我们存数据取数据,并没有界面,可以看作一个数据库,只能对文本信息进行检索)Lucene.Net原理:把文本切词保存,然后根据词汇表的页来找到文章 二  分词算法: //一元分词算法(引用Lucene.Net.dll)  一元分词算法 //二元分词算法(CJK:China Japan Korean 需要再

Lucene.net站内搜索1——SEO优化简介

声明:在这里,所谈的一切关于SEO的技术主要针对于我们开发人员. SEO (搜索引擎优化) SEO(搜索引擎优化)的目的(很多人都是通过搜索引擎找到我们的网站)是让搜索引擎更多的收录网站的页面,让被收录页面的权重更靠前,让更多的人能够通过搜索引擎进入这个网站 原理:蜘蛛会定时抓取网站的内容,发现网站内容变化.发现新增内容就反映到搜索引擎中 蜘蛛(spider) 爬网站:就是向网站发http get请求的客户端. SEO(搜索引擎优化*):让网站排名靠前,让网站更多的页面被搜索引擎收录.链接(外链

B2C商城关键技术点总结(站内搜索、定时任务)

1.站内搜索 1.1Lucene.Net建立信息索引 1 string indexPath = @"E:\xxx\xxx";//索引保存路径 2 FSDirectory directory = FSDirectory.Open(new DirectoryInfo(indexPath), new NativeFSLockFactory()); 3 bool isUpdate = IndexReader.IndexExists(directory); 4 if (isUpdate) 5 {

借助 Lucene.Net 构建站内搜索引擎(上)

前言:最近翻开了之前老杨(杨中科)的Lucene.Net站内搜索项目的教学视频,于是作为老杨脑残粉的我又跟着复习了一遍,学习途中做了一些笔记也就成了接下来您看到的这篇博文,仅仅是我的个人笔记,大神请呵呵一笑而过.相信做过站内搜索的.Net程序员应该对Lucene.Net不陌生,没做过的也许会问:就不是个查询嘛!为什么不能使用Like模糊查找呢?原因很简单:模糊查询的契合度太低,匹配关键字之间不能含有其他内容.最重要的是它会造成数据库全表扫描,效率低下,即使使用视图,也会造成数据库服务器"亚历山大

利用Solr服务建立的站内搜索雏形

最近看完nutch后总感觉像好好捯饬下solr,上次看到老大给我展现了下站内搜索我便久久不能忘怀.总觉着之前搭建的nutch配上solr还是有点呆板,在nutch爬取的时候就建立索引到solr服务下,然后在solr的管理界面中选择query,比如在q选项框中将"*:*"改写为"title:安徽",则在管理界面中就能看到搜索结果,可是这个与搜索引擎的感觉差远了,总感觉这些结果是被solr给套在他的管理界面中了,于是自己在网上搜索,也想整个站内搜索一样的东西,就算整不到

1.PHP站内搜索

PHP站内搜索:多关键字.加亮显示 1.SQL语句中的模糊查找 $sql = "SELECT * FROM `message` WHERE `content`like '%$k[0]%' and `content`like '%$k[0]%'"; 2.多个关键字搜索的原理和技巧 3.替换关键字高亮显示 $r[content] = preg_replace("/($_GET[key])/i", "<font color = red><b&g