Ivan's world

search engine, distributed system, asp.net, c#

WEBUS2.0 In Action - 开始搜索

上一篇:WEBUS2.0 In Action - 编制索引  | 下一篇:WEBUS2.0 In Action - 解析索引文件结构(1)

当索引建好之后,要利用WEBUS2.0实现基本搜索功能,至少需要用到如下几个类和接口:
Webus.Index.IIndexReader (接口)
Webus.Index.IndexManager (类,实现IIndexReader)
Webus.Analysis.IAnalyzer (接口)
Webus.Analysis.SimpleWordAnalyzer (类,实现IAnalyzer)
Webus.Search.ISearcher (接口)
Webus.Search.IndexSearcher (类,实现ISearcher)
Webus.Search.Query (类,用于构造搜索表达式)

下面我用一个文件搜索的小例程来说明如何开发搜索功能:
FileSearcher.exe
× 首先选择要编制索引的文件(文本文件,源代码等等皆可):


× 直接输入关键词(多个关键词用空格区分)进行搜索:


要实现如上功能其实很简单,首先我们要声明几个需要用到的对象:

IIndexWriter writer; //索引writer
IIndexReader reader; //索引reader
ISearcher searcher;  //搜索器

并在窗体构造函数中构造它们:

public frmMain()
{
    InitializeComponent();

    writer 
= new IndexManager(new SimpleWordAnalyzer());
    reader 
= new IndexManager();
    searcher 
= new IndexSearcher(reader);
}

注意这里使用了SimpleWordAnalyzer去构造writer,这是因为WEBUS在编制索引时需要将文件内容分切成多个语汇单元(token)再对每个语汇单元编制索引。利用不同的分析器(Analyzer)可以分切出不同的语汇单元,从而实现各种各样的分析效果。我们这里使用的最简单的内置分析器SimpleWordAnalyzer,它会将英文分割成单词,将中文分割成字,并将所有语汇单元转换成小写形式。

当对象构造完成之后,我们读取选定的文件内容并将其添加到索引中:

writer.New(indexPath);
foreach (string file in openFileDialog1.FileNames)
{
    
using (StreamReader sr = new StreamReader(file))
    
{
        Document doc 
= new Document();
        doc.Fields.Add(
new Field("FileName", file));
        doc.Fields.Add(
new Field("Content", sr.ReadToEnd(),
            FieldAttributes.Analyse 
| FieldAttributes.Index | FieldAttributes.Compress));
        writer.Add(doc);
    }

}

writer.Close(); 

对于FileName字段,我们采用Default(Default=Index|Sort)的方式编制索引;对于Content字段,我们需要首先分析(Analyse)然后编制索引(Index)并且要压缩保存(Compress)。
当索引编制完成之后,我们需要关闭writer(writer.Close())才能够用reader读取它:

reader.Open(indexPath, IndexOpenMode.Read);

OK,一切就绪,现在我们来为TextBox控件的TextChanged事件添加搜索代码,如此一来就可以实现一输入关键词立马显示相关搜索结果的功能:

//用空格分割用户输入的关键词
tvResult.Nodes.Clear();
string[] keys = txtKeyword.Text.Split(' ');
//构造一个 "key1 AND key2 AND key3 " 类型的Query
Query query = null;
foreach (string key in keys)
{
    Query q 
= new TermQuery(new Term("Content", key));
    
if (query == null)
    
{
        query 
= q;
    }

    
else
    
{
        query 
&= q; //用"&" (AND)操作符对两个Query进行计算,结果为一个新的Query对象
    }

}

Hits hits 
= searcher.Search(query);//搜索

这里需要注意的是Query的运算。目前在WEBUS中有7种Query:
TermQuery        基本Term搜索
PrefixQuery      前缀搜索
PostfixQuery     后缀搜索
WildcardQuery    通配符搜索
RegexQuery       正则表达式搜索
RangeQuery       范围搜索
BooleanQuery     布尔搜索
它们之间可以支持如下运算符:
+ - ! & |
其中 !a 就是非 a 的意思;
a + b 就是 a AND b 的意思;
a - b 就是 a AND !b 的意思;
a | b 就是 a OR b 的意思;
& 和 + 是相同的效果。
任何两个Query之间通过运算之后的结果都将是一个BooleanQuery对象,通过这种方式,我们可以实现十分复杂的搜索效果!

到此为止,绝大部分代码我们已经完成了,只需要将搜索结果显示出来这个程序就OK了:

for (int i = 0; i < hits.Count; i++)
{
    Document doc = hits.GetDoc(i); //获取Document对象
    TreeNode node = tvResult.Nodes.Add(doc["FileName"].Value.ToString()); //从Doc中获取FileName字段的值
    
string content = doc["Content"].Value.ToString(); //获取Content字段的值
    
foreach (Position pos in hits[i].Positions)
    
{
        
int h = content.LastIndexOf("\n", pos.Start);
        
int t = content.IndexOf("\n", pos.Start + pos.Length);
        h 
= h >= 0 ? h : 0;
        
int l = t - h;
        l 
= l >= 0 ? l : 0;
        node.Nodes.Add(
string.Format("[Position: {0}]   {1}", pos.Start, content.Substring(h, l).Trim()));
    }

}

完整代码下载:FileSearch c# .Net2.0

相关信息及WEBUS2.0 SDK下载:继续我的代码,分享我的快乐 - WEBUS2.0

posted on 2008-01-05 10:35 Ivan Zou 阅读(1906) 评论(9)  编辑 收藏 所属分类: WEBUS

Feedback

#1楼  2008-01-05 11:23 蛙蛙池塘      

又一lucene出来了,呵呵   回复  引用  查看    

#2楼  2008-01-05 14:05 某某鸟人      

和lucene有什么区别?
索引存储结构是怎样的?也和lucene一样?   回复  引用  查看    

#3楼  2008-01-05 14:19 没剑      

这个是封装lucene的吧~   回复  引用  查看    

#4楼  2008-01-05 14:27 lfy [未注册用户]

没有怎么看懂啊,封装lucene?
http://www.28cx.cn   回复  引用    

#5楼  2008-01-05 17:17 zhuweisky      

今天在博客园溜达,无意中看到Ivan你的博文,不错,呵呵,最近文章发表的很频繁哦,好东西要多拿出来晒晒啊,继续加油!   回复  引用  查看    

#6楼 [楼主] 2008-01-05 21:59 Ivan Zou      

呵呵,不是封装。Lucene的V-Twins结构很高效,WEBUS的BHS文件结构也很不错。本质而言,两者就是不同的东西,只不过接口类似而已。

zhuweisky,谢谢鼓励。还要你的多多支持啊!   回复  引用  查看    

#7楼  2008-01-07 10:23 补丁      

相比lucene有啥优势?   回复  引用  查看    

#8楼  2008-03-07 16:27 暗香浮动      

@Ivan Zou
Lucene的V-Twins结构很高效
对这个由研究么,比较感兴趣但是又没发现什么比较合适的资料。   回复  引用  查看    

#9楼 [楼主] 2008-03-10 13:25 Ivan Zou      

@暗香浮动

呵呵,研究过Lucene的索引结构。主要靠文件和文件间的Position来保持关系,有点复杂。个人认为如果想在索引文件结构这一层来扩展Lucene会比较困难。   回复  引用  查看    


标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2008-03-20 15:54 编辑过


相关链接: