I. Intro
前几天我赶着做了一个股票搜索的demo,总算是有了一个成型的东西。这几天一直在看资料,为下一个milestone准备着......
II. Open Issues
从编程的角度看来Lucene就是一个只支持纯文本检索的类库(Oops!!!):没有 spider,不支持html、doc、pdf等复杂类型的文本检索。而作者Doug Cutting的另一个masterpiece---Nutch则是一个complete search engine application,它在底层调用了Lucene提供的功能。要想进步,必须得看Nutch源码。目前Nutch还没有其它语言的port,暴汗不 已。
III. Road to Glory
1. Ad Hoc IR vs. Filtering IR
In a conventional information retrieval system, the documents in the collection remain relatively static while new queries are submitted to the system. This operational mode has been termed ad hoc retrieval in recent years and is the most common form of user task. A similar but distinct task is one in which the queries remain relatively static while new documents come into the system (and leave). For instance, this is the case with the stock market and with news wiring services. This operational mode has been termed filtering.
按照Modern IR这本书的定义,我认为股票搜索引擎应该属于filtering IR system:查询相对固定,现阶段也就是公司的名称或者股票代码。而待检索文档更新很快,尤其是公司新闻和股评部分。网上好像有rss支持新闻分类的什么东东,没碰过。
2. Inside Nutch
Keyword:
Servlet/JSP
Java Beans
Dynamic plugin loading
Reflection
粗 略看了一下Nutch的源码,最想说的一句话是:像nutch这种好东东,咱不但要看明白系统工作的机理,还要重视学习代码里的一些模式、用法。比如说 singleton, publisher/subscriber模式,plugin的动态加载,logger的用法等等。参看ref[1]。用于动态配置nutch spider(这里叫fetcher)的文件crawl-urlfilter.txt。nutch里居然还有一个关于什么语义网的ontology包,暴 强啊。
主流程
粗略看了一下,UI主体是一个jsp文件:search.jsp,有文本框、搜索按钮等基本UI元素。在后台进行处理请求的是一个servlet和一个java bean:NutchBean。它们负责调用相应的功能组件。
plugin的动态加载
我 觉得这是nutch里面最出彩的部分:core里面只是定义了一些interface和相应的wrapper类,而在使用plugin的时候(late binding)才动态加载相应的implementation(s)进来。low coupling, high cohesion,哈哈。听说Eclipse的插件机制与之类似,不过它使用了更为复杂的插件协议。
org.apache.nutch.plugin 包里有几个类实现了插件的动态加载:Extension类可以说是一个listener,而相应的ExtensionPoint是一个 publisher。一个类可以有多个扩展点,像org.apache.nutch.parse.html.HtmlParser就实现了两个扩展 点:org.apache.nutch.parse.Parser和org.apache.nutch.parse.HtmlParseFilter。 PluginDescriptor定义了一个插件所有的metadata:包括路径、名称、版本、扩展点、依赖项和exportlib。 PluginDescriptor包容在Plugin类里。而PluginRepository相当于plugin的注册表,维护当前所有注册过的插件。 注册项是通过一个xml文件来定义,它由PluginManifestParser来负责解析。
下面结合parsing和indexing部分谈一谈这些模块的工作机理和plugin的结构
索引core及其plugin
core中indexing interface是IndexingFilter,wrapper类是IndexingFilters
IndexingFilters中:
private static final IndexingFilter[] CACHE;
static {
// Get plug-in implementations at run-time
}
public static Document filter(Document doc, Parse parse, FetcherOutput fo)
throws IndexingException {
for (int i = 0; i < CACHE.length; i++) {
doc = CACHE[i].filter(doc, parse, fo);
}
return doc;
}
可 以看到,wrapper类将各个实现的filter方法包成了一个静态方法,由各个实现进行串行处理。像MoreIndexingFilter在 BasicIndexingFilter的基础上为文本的检索添加了一些fields。我查看了Nutch(BasicIndexingFilter 类),lucene的case study中jGuru(www.jguru.com)、 The Server Side(www.theserverside.com)的索引内容,它们都没有保存全文内容。这个问题我一直很困惑,因为我观察这些网站的检索是能够做到全文匹配的。到水母上发帖询问(ref[2]),一个dx回帖说全文在parse后还是保存了的。where???@#^&%*(*^*......看来还得继续研究@_@
parse core及其plugin
parse的机理与之类似,接口是Parser类,wrapper类是ParserFactory类
对一个特定扩展名的文件,好像是在所有的parser plugins中寻找相应扩展名的Parser实现进行处理
ref
1. Classes of Importance: PluginRepository, NutchConf, NutchFileSystem, LogFormatter
2. 请教:搜索引擎索引时保存不保存文本全文?, AI board, www.newsmth.net