当前位置: 代码迷 >> 综合 >> Lucene.net 盘古分词 站内搜索
  详细解决方案

Lucene.net 盘古分词 站内搜索

热度:36   发布时间:2023-12-12 07:09:46.0

Q:站内搜索为什么不能使用Like模糊查找

A:模糊契合度太低,匹配关键字之间不能含有其他内容。最重要的是它会造成全表扫描,效率底下,即使使用视图,也会造成数据库服务器"亚历山大"

Lucene简介

Lucene.NET只是一个全文检索开发包,不是一个成型的搜索引擎

它提供了类似SQLServer数据库正式版中的全文检索功能的索引库

你把数据扔给Lucene.Net,【Lucene.Net只针对文本信息建立索引,所以他只接收文本信息,如果不是文本信息,则要转换为文本信息】它会将文本内容分词后保存在索引库中,当用户输入关键字提交查询时,Lucene.Net从索引库中检索关键字数据,所以搜索速度非常快,适合于用户开发自己站内的搜索引擎

Q:分词

A:即将"不是所有痞子都叫一毛"文本内容通过分词算法  分割成为“不是” “所有” “痞子” “都” “叫” "一毛"  。 但是Lucene.Net内置分词算法对中文支持不是很好,以下会使用国内较为流行的分词算法 -- 盘古分词

以下是运行图解:

下面以用户查询数据库Book表   内容描述【对应字段名:ContentDescription】中包含其输入的关键字key的数据  演示Lucene.Net使用

运行界面效果如下:

 

本人使用的盘古分词版本为V2.3.1.0  Lucene.Net2.9

在项目下新建Dict文件以及dll文件包含Lucene与盘古分词所需的组件及文件信息如图示

1、项目添加对dll文件夹中四个程序集的引用

2、添加图书搜索页面SearchBlogs.aspx代码如下:

<% @ Page Language="C#" AutoEventWireup="true" CodeBehind="SearchBook.aspx.cs" Inherits ="BookShop.Web.SearchBook" %>
<! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
< html xmlns ="http://www.w3.org/1999/xhtml">
< head runat ="server"><title ></ title>
</ head>
< body><form id="form1" runat="server"><asp : TextBox ID ="txtSerach" runat ="server" Width ="494px"></asp : TextBox><asp : Button ID ="btnSearch" runat ="server" onclick ="btnSearch_Click" Text ="搜索" /><asp : Button ID ="CreateView" runat ="server" onclick ="CreateView_Click" Text ="创建索引" /><div >< asp: Repeater ID ="Repeater1" runat ="server">< ItemTemplate>< table>< tbody>< tr>< td style ="font-size : small; color: red" width="650">< a  id ="link_prd_name" href ='<% # Eval("Id","/book.aspx?id={0}") %> 'target ="_blank" name ="link_prd_name"><%Eval"Title"%></ a></ td></ tr>< tr>< td align ="left">< span style ="font-size : 12px; line-height: 20px"><%Eval"ContentDescription"%></ span ></ td></ tr></ tbody></ table></ ItemTemplate></ asp: Repeater ></div ></form >
</ body>
</ html>

3、后台调用

using System;
using System.Collections.Generic;
using System.IO;
using BookShop.BLL;
using Lucene.Net.Analysis.PanGu;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.Search;
using Lucene.Net.Store;
namespace BookShop.Web {public partial class SearchBook : System.Web.UI. Page {protected void Page_Load( object sender, EventArgs e) {}//创建索引事件  可以防止在用户点击查询事件前执行 去掉页面中的"创建索引"按钮protected void CreateView_Click( object sender, EventArgs e) {string indexPath = @"C:\luceneTest" ; //索引文档保存位置FSDirectory directory = FSDirectory .Open( new DirectoryInfo (indexPath), new NativeFSLockFactory ());bool isUpdate = IndexReader .IndexExists(directory); //是否存在索引库文件夹以及索引库特征文件if (isUpdate) {//如果索引目录被锁定(比如索引过程中程序异常退出或另一进程在操作),则解锁if (IndexWriter .IsLocked(directory)) {IndexWriter .Unlock(directory);}}//创建索引库对象   new PanGuAnalyzer()指定使用盘古分词进行切词IndexWriter writer = new IndexWriter(directory, new PanGuAnalyzer (), !isUpdate, Lucene.Net.Index.IndexWriter . MaxFieldLength.UNLIMITED);BooksManager bookManager new BooksManager();List <Model.Books > bookList = bookManager.GetModelList( "" );foreach (var book in bookList) {Document document new Document(); //new 一篇文档 对象//所有字段的值都将以字符串类型保存//Field.Store表示是否保存字段原值。指定Field.Store.YE的字段在检索时才能用document.Get取出来值  NOT_ANALYZED指定不按照分词后的结果保存document.Add( new Field ( "id", book.Id.ToString(), Field .Store .YES, Field .Index .NOT_ANALYZED));document.Add( new Field ( "title", book.Title, Field .Store .YES, Field .Index .ANALYZED, Lucene.Net.Documents.Field .TermVector .WITH_POSITIONS_OFFSETS));//Field.Index. ANALYZED指定文章内容按照分词后结果保存  否则无法实现后续的模糊查找  WITH_POSITIONS_OFFSETS指示不仅保存分割后的词 还保存词之间的距离document.Add( new Field ( "content", book.ContentDescription, Field .Store .YES, Field. Index .ANALYZED, Lucene.Net.Documents.Field .TermVector .WITH_POSITIONS_OFFSETS));writer.AddDocument(document); //文档写入索引库
            }writer.Close();directory.Close(); //不要忘了Close,否则索引结果搜不到
        }protected void btnSearch_Click( object sender, EventArgs e) {string indexPath = @"C:\luceneTest" ;FSDirectory directory = FSDirectory .Open( new DirectoryInfo (indexPath), new NoLockFactory ());IndexReader reader = IndexReader .Open(directory, true);IndexSearcher searcher new IndexSearcher(reader); //Index:索引//搜索条件PhraseQuery query = new PhraseQuery();//把用户输入的关键字进行分词foreach (string word in Common.SplitContent .SplitWords(txtSerach.Text.ToLower())) {query.Add( new Term ( "content", word));}query.SetSlop(100); //指定关键词相隔最大距离//TopScoreDocCollector盛放查询结果的容器TopScoreDocCollector collector = TopScoreDocCollector .create(1000true );searcher.Search(query, null , collector);//根据query查询条件进行查询,查询结果放入collector容器//TopDocs 指定0到GetTotalHits() 即所有查询结果中的文档ScoreDoc [] docs = collector.TopDocs(0, collector.GetTotalHits()).scoreDocs;//展示数据实体对象集合List <Model.Books > bookResult = new List <Model.Books >();for (int i = 0; i < docs.Length; i++) {//需要获得文档的详细内容的时候通过searcher.Doc来根据文档id来获得文档的详细内容对象Documentint docId = docs[i].doc;//得到查询结果文档的id(Lucene内部分配的id)Document doc = searcher.Doc(docId);//找到文档id对应的文档详细信息Model. Books book = new Model. Books();book.Title = doc.Get( "title" );//book.ContentDescription = doc.Get("content");//未使用高亮//搜索关键字高亮显示book.ContentDescription = Common.SplitContent .HightLight(txtSerach.Text, doc.Get("content" ));book.Id = Convert .ToInt32(doc.Get("id" ));bookResult.Add(book);}//设置Repeater1  绑定查询结果集合Repeater1.DataSource = bookResult;Repeater1.DataBind();}}
}

4、使用到的公共类 Common下的SplitContent

using System.Collections.Generic;
using System.IO;
using Lucene.Net.Analysis;
using Lucene.Net.Analysis.PanGu;
using PanGu;
namespace BookShop.Web.Common {public class SplitContent {public static string[] SplitWords( string content) {List <string > strList = new List <string >();Analyzer analyzer new PanGuAnalyzer();TokenStream tokenStream = analyzer.TokenStream("" , new StringReader (content));Lucene.Net.Analysis. Token token null ;while ((token = tokenStream.Next()) != null ) { //Next继续分词 直至返回nullstrList.Add(token.TermText()); //得到分词后结果
            }return strList.ToArray();}//需要添加PanGu.HighLight.dll的引用/// <summary>/// 搜索结果高亮显示/// </summary>/// <param name="keyword"> 关键字 </param>/// <param name="content"> 搜索结果 </param>/// <returns> 高亮后结果 </returns>public static string HightLight( string keyword, string content) {//创建HTMLFormatter,参数为高亮单词的前后缀PanGu.HighLight. SimpleHTMLFormatter simpleHTMLFormatter =new PanGu.HighLight.SimpleHTMLFormatter ( "<font color=\"red\"><b>""</b></font>" );//创建 Highlighter ,输入HTMLFormatter 和 盘古分词对象SemgentPanGu.HighLight. Highlighter highlighter =new PanGu.HighLight.Highlighter (simpleHTMLFormatter,new Segment ());//设置每个摘要段的字符数highlighter.FragmentSize = 50;//获取最匹配的摘要段return highlighter.GetBestFragment(keyword, content);}}
}

5、使用DictDll文件夹以及盘古分词的开发文档点击下载        实际应用中当然不会存在上图中的创建索引按钮  而且索引需随数据库数据同步更新   本章暂不介绍



http://blog.csdn.net/wangyizhi58/article/details/8705172

  相关解决方案