搜索引擎lucene实现--二半吊子的论调之体系结构
写这个东西就是两个目的,一是让自己头脑清醒,一是让别人把咱的头脑弄清醒。技术这个东西跟本能一个样,只要你愿意用成就本能的方式去学习技术,谁都可以成就自己。
因为咱不是文科出身,工作了六年,也没有那些牛逼人士的韧力和魄力,曾经就想着能多写写技术博客,但总是没有坚持下去(深叹一口气,你可别像我这样。。)。前些日子又看了一下《康熙王朝》(陈道明演的),被里面的一句话(一言之虚,百患丛生; 一事之虚,遗害终生。)给击蒙了,于是重新想着坚持下去。刚好要跟同事分享lucene,那么也就多学,多看,多想,多写了。
OK,言归正传,到底搜索引擎有多神秘?
对我来说,lucene的出现,没有多少影响,因为当初我还在一个小公司里面糊里糊涂地混日子,而虽然听说过这个东西,但没有用过,仅了解了一下。但自从去了那个网络公司之后,要做搜索系统,我就切实地接触到了这个开源神器。至少在一定程度上讲,让我觉得Google,百度不是那么神奇的公司了。因为他们就是用超大规模的爬虫,倒排表,超大规模的缓存和我不知道的超大的things。
小差时刻:作为一个非计算机专业的从业人员,从一定程度上讲,个人表示很惭愧。尽管有编程之热情,但却没有彻底地钻研从业用到的每个组成部分,这实在有点非专业的风格。我想这个浮躁的社会可能会让很多人变成(编程)这样,Matrix造就了我们追求成果不管原理的工作方式。(抱怨一下,但这是自我深深的反省。)
看一段lucene官网的示例代码:
1 import org.apache.lucene.analysis.Analyzer; 2 import org.apache.lucene.analysis.standard.StandardAnalyzer; 3 import org.apache.lucene.document.Document; 4 import org.apache.lucene.document.Field; 5 import org.apache.lucene.document.TextField; 6 import org.apache.lucene.index.DirectoryReader; 7 import org.apache.lucene.index.IndexWriter; 8 import org.apache.lucene.index.IndexWriterConfig; 9 import org.apache.lucene.queryparser.classic.QueryParser; 10 import org.apache.lucene.search.IndexSearcher; 11 import org.apache.lucene.search.Query; 12 import org.apache.lucene.search.ScoreDoc; 13 import org.apache.lucene.store.Directory; 14 import org.apache.lucene.store.RAMDirectory; 15 import org.apache.lucene.util.Version; 16 17 public final class TestLucene { 18 19 public static void main(String[] args) throws Exception{ 20 Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_CURRENT); 21 22 // Store the index in memory: 23 Directory directory = new RAMDirectory(); 24 // To store an index on disk, use this instead: 25 //Directory directory = FSDirectory.open("/tmp/testindex"); 26 IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_CURRENT, analyzer); 27 IndexWriter iwriter = new IndexWriter(directory, config); 28 Document doc = new Document(); 29 String text = "This is the text to be indexed."; 30 doc.add(new Field("fieldname", text, TextField.TYPE_STORED)); 31 iwriter.addDocument(doc); 32 iwriter.close(); 33 34 // Now search the index: 35 DirectoryReader ireader = DirectoryReader.open(directory); 36 IndexSearcher isearcher = new IndexSearcher(ireader); 37 // Parse a simple query that searches for "text": 38 QueryParser parser = new QueryParser(Version.LUCENE_CURRENT, "fieldname", analyzer); 39 Query query = parser.parse("text"); 40 ScoreDoc[] hits = isearcher.search(query, null, 1000).scoreDocs; 41 // Iterate through the results: 42 for (int i = 0; i < hits.length; i++) { 43 Document hitDoc = isearcher.doc(hits[i].doc); 44 System.out.println(hitDoc.get("fieldname")); 45 } 46 ireader.close(); 47 directory.close(); 48 } 49 50 }
声明:以上这段代码,main里面的代码都是取自lucene官网的。但也要特别说明一下,在maven pom.xml里面,对于lucene4.0版本的依赖配置如下:
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-common</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-queryparser</artifactId>
<version>4.0.0</version>
</dependency>
好像3.x版本的不需要这么多配置的吧(好像又好久没跟进lucene测试了。。呵呵)
仅仅从这个demo的import里面,我们能看到lucene的基本功能结构分割:
Lucene是一个文本内容的全文检索系统,从上图我们也可以看出lucene的确有比较明确且抽象的架构设计。
IndexWriter:接收业务数据,并将索引好的数据写入到Store中。IndexWriter在接收数据时,主要依靠封装了文本内容及其元数据的Document(org.apache.lucene.document,夹缝中引用一下,实在是委屈了Document,它也是具有皇室直系血统的类,非常重要。),它在org.apache.lucene.index包中。index包主要管理索引创建阶段用到的各种类,如IndexReader, IndexWriter....(还有很多底层类,不一一列举,但后面在详细说明时,会一一分析。)
Store:这是一个相对底层的组织,对应包为org.apache.lucene.store,其主要包含与索引数据文件读写管理相关的各种类。
IndexSearcher: 这个是使用Query数据对索引数据进行检索的类。猜得出来,它在org.apache.lucene.search中。
QueryParser:它也是存在于org.apache.lucene.search中,并且其主要职责是解析用户的输入字符串,并返回Query对象,然后供IndexSearcher使用,其对IndexSearcher的重要性跟Docment之于IndexWriter有的一拼。
Analyzer:最后才说到Analyzer,并不是说它不重要,相反它极其重要。Analyzer类主要用户对文本内容进行分词处理,而分词质量的好坏关系到搜索结果的相关度,所以也就有了针对不同文化和语言的各种Analyzer。正如图中展现的,建立和查询索引时都要用到它,是居家旅行的必备良药。
对于网络用户来说,他们只需要关心query data(就是他们想搜的关键词或者句子),经过Parser解析成关键字的query(queryparser的结果),经由IndexSearcher来查询Indexed Data,并返回结果。而我们在对目标数据建索引的过程,则是经由IndexWriter来解析和分解处理,然后将解析的结果(这是个big problem)保存成Indexed Data。
这里要区分一下,网络用户他们只想查找关心的数据,所以他们输入:关键词;而我们开发者则有业务数据。这里就是说,在使用lucene时,是否需要想想以下几个方面:
数据获取:提供用于接收业务数据的接口,搜索请求处理接口;
lucene封装:组装索引Document的接口,返回结果的封装接口,更重要的是log接口(统计和实验);
瞻前顾后,咱会从Analyzer,Document,Index,Search and Store几个方面,给各位分享一下lucene的情况。
一点点来,不着急。。。。。
posted on 2012-11-18 20:18 eric_chen 阅读(3332) 评论(2) 编辑 收藏 举报