利用Lucene.net搭建站内搜索(3)---创建索引

Lucene.net索引创建
本文介绍如何使用Lucene.net创建数据索引,包括将数据转换为文本、分析文本及保存到索引库的过程。同时提供了针对Access数据库数据的具体索引创建示例。

Lucene.net提供了很全面的数据搜索操作,你可以利用Lucene.net检索磁盘中的文件,网页,数据库中的数据,但是前提是预先对数据创建索引。
Lucene索引过程分为三个主要的操作阶段:将数据转换成文本分析文本、并将分析过的文本保存到索引库中。如图所示:

1.数据转成文本:须将数据转换成Lucene能够处理的格式——纯文本字符流。

2.分析文本:完成了针对待索引数据的预处理操作,并创建了带有若干个域的Document对象,就可以调用IndexWriter的addDocument(Document)方法,将数据传递给Lucene来进行索引操作。在对数据进行索引处理时,Lucene会首先分析(analyze)数据使之更加适合被索引。

3.将分析过的文本保存到索引库中:对输入数据分析处理完之后,就可以将结果写入到索引文件中。Lucene将输入数据以一种称为倒排索引(inverted index)的数据结构进行存储。在进行关键字快速查找时,这种数据结构能够有效地利用磁盘空间。

下面介绍下Lucene.net中处理索引的类
IndexWriter
IndexWriter是索引中负责操作的核心,它负责把索引文件写入存储介质,是控制逻辑存储转换为物理存储的纽带。

Document
Document就是一条虚拟记录,可以理解为数据里的一行。正是有了它,才使我们可以很方便并且易于理解地操作索引文件。它一般记录了需要用到的一个文档的属性,当然,这需要和Field联合使用。

Field
Field类就是数据库里的一列。一个文档有标题,内容,作者,创建时间这四个属性的话,那么就需要四个Field保存这些属性,然后把四个Field加入到Document中。
Field的构造函数比较多。其中Store,Index和TermVector是通过内部类指定的。

(1)--Store 有三个选项:
Field.Store.COMPRESS表示被压缩存储;
Field.Store.YES表示储存;
Field.Store.NO表示不被存储。

(2)--Index的选项有四个:
Field.Index.NO表示不建立索引;
Field.Index.TOKENIZED表示分词后索引;
Index.NO_NORMS表示值存储内容;
Field.Index.UN_TOKENIZED表示不分词索引。

(3)--TermVector这个参数也不常用,它有五个选项。
Field.TermVector.NO表示不索引Token的位置属性;
Field.TermVector.WITH_OFFSETS表示额外索引Token的结束点;
Field.TermVector.WITH_POSITIONS表示额外索引Token的当前位置;
Field.TermVector.WITH_POSITIONS_OFFSETS表示额外索引Token的当前和结束位置;
Field.TermVector.YES则表示存储向量。

通过实例生成数据索引:

这里我将数据保存在Access数据库中,对Access数据库中的数据进行索引:
保存数据的表:数据库中保存了1000条数据

为数据创建索引代码:

ContractedBlock.gifExpandedBlockStart.gifCode
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->usingSystem;
usingSystem.Data;
usingSystem.Configuration;
usingSystem.Web;
usingSystem.Web.Security;
usingSystem.Web.UI;
usingSystem.Web.UI.WebControls;
usingSystem.Web.UI.WebControls.WebParts;
usingSystem.Web.UI.HtmlControls;

usingSystem.Collections.Generic;
usingSystem.Text;
usingSystem.IO;
usingSystem.Text.RegularExpressions;
usingSystem.Data.SqlClient;
usingLucene.Net.Analysis;
usingLucene.Net.Documents;
usingLucene.Net.Index;
usingLucene.Net.Analysis.KTDictSeg;
usingLuceneSearch;

///<summary>
///CreateIndex的摘要说明
///</summary>
publicclassCreateIndex
{
//词库路径
publicstringwordPath;
publicstringindexDirectory;
//定义一个IndexWriter
protectedIndexWriterwriter=null;
//需要导出的数目
publicintallNum;
//当前完成的数目
publicintcompleteNum;
//需要生成的表
publicDataTabledt;

DAL.OperSqlos
=newDAL.OperSql();
publicCreateIndex()
{

}

publicvoidGetIndex(intinum)
{
//定义分析器
AnalyzerKTDAnalyzer=newKTDictSegAnalyzer(wordPath);

//PerFieldAnalyzerWrapper可以对不同的Field进行不同的分析
PerFieldAnalyzerWrapperwrapper=newPerFieldAnalyzerWrapper(KTDAnalyzer);

wrapper.AddAnalyzer(
"ID",KTDAnalyzer);
wrapper.AddAnalyzer(
"News_Url",KTDAnalyzer);
wrapper.AddAnalyzer(
"News_Date",KTDAnalyzer);

//判断是否已有索引
boolisure=!IndexReader.IndexExists(indexDirectory);
//创建索引的数据条数
allNum=dt.Rows.Count;
//创建IndexWriter
writer=newIndexWriter(indexDirectory,wrapper,isure);
writer.SetUseCompoundFile(
true);//显式设置索引为复合索引
writer.SetMaxFieldLength(int.MaxValue);//设置域最大长度为最大值
writer.SetMergeFactor(allNum+100);//设置每100个段合并成一个大段
writer.SetMaxMergeDocs(10000);//设置一个段的最大文档数
writer.SetMaxBufferedDocs(1000);//设置在把索引写入磁盘前内存里文档的缓存个数
//创建IndexReader
IndexReaderreader=null;
boolneedre=inum==1;

reader
=IndexReader.Open(indexDirectory);
for(inti=0;i<dt.Rows.Count;i++)
{
completeNum
=i+1;
stringbody=parseHtml(dt.Rows[i]["News_Body"].ToString());
stringtitle=parseHtml(dt.Rows[i]["News_Title"].ToString());

if(title.Length>2&&body.Length>2)
{
if(needre)
{
Termterm
=newTerm("ID",dt.Rows[i]["ID"].ToString());
reader.DeleteDocuments(term);

}
Documentdocument
=newDocument();

document.Add(
newField("ID",dt.Rows[i]["ID"].ToString()??"",Field.Store.YES,Field.Index.UN_TOKENIZED));
document.Add(
newField("News_Title",title,Field.Store.NO,Field.Index.TOKENIZED));
document.Add(
newField("News_Body",body,Field.Store.NO,Field.Index.TOKENIZED));
document.Add(
newField("News_Url",dt.Rows[i]["News_Url"].ToString()??"",Field.Store.YES,Field.Index.UN_TOKENIZED));
document.Add(
newField("News_Date",DateField.DateToString(Convert.ToDateTime(dt.Rows[i]["News_Date"].ToString()))??"",Field.Store.YES,Field.Index.UN_TOKENIZED));
writer.AddDocument(document);;
}
}
reader.Close();
writer.Optimize();
writer.Close();

}
}

传入参数,生成索引文件:

ContractedBlock.gifExpandedBlockStart.gifCode
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->try
{
ci.wordPath
=Server.MapPath("App_Data")+@"\";//词库路径;
ci.indexDirectory=Server.MapPath("index")+@"\";//词库路径;
ci.dt=dt;
ci.GetIndex(
1);
}

其中dt是保存数据的DataTable,wordpath是分词器的词库文件chsstopwords.txt,engstopwords.txt,dict.dct的路径,indexDirectory是生成索引文件的路径。
生成索引成功后,我们会在index文件夹下看到生成的文件:

这样,我们就创建好了数据的索引。检索数据的时候,我们就可以利用它快速的对数据进行检索。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值