- 浏览: 93670 次
- 性别:
文章分类
最新评论
-
softkid:
pool中的string对象会不会被GC回收啊?
String s = new String("abc");你真的了解吗??? -
sarsgetaway:
[b]public String readTemple(Str ...
jsp生成html -
phoenix:
建议增加web.xml关于此filter的配置文件
用于检测用户是否登陆的过滤器
Lucene是apache组织的一个用java实现全文搜索引擎的开源项目。其功能非常的强大,api也很简单。总得来说用Lucene来进行建立和搜索与操作数据库是差不多的,Document可以看作是数据库的一行记录,Field可以看作是数据库的字段。用lucene实现搜索引擎就像用JDBC实现连接数据库一样简单。
值得一提的是:2006年6月1号Lucene2.0发布,它与以前广泛应用和介绍的Lucene 1.4.3并不兼容。 有了很大的改进和优化,这里只介绍的是Lucene 2.0。
Lucene2.0的下载地址是 http://apache.justdn.org/lucene/java/
大家先看一个例子,通过这个例子来对lucene的一个大概的认识。 一个Junit测试用例:(为了让代码清晰好看,我们将异常都抛出)
a) 这是一个建立文件索引的例子
public void testIndexHello() throws IOException{ Date date1 = new Date(); //可以说是创建一个新的写入工具 //第一个参数是要索引建立在哪个目录里 //第二个参数是新建一个文本分析器,这里用的是标准的大家也可以自己写一个 //第三个参数如果是true,在建立索引之前先将c:\\index目录清空。 IndexWriter writer = new IndexWriter("c:\\index",new StandardAnalyzer(),true); //这个是数据源的文件夹 File file = new File("c:\\file"); /** * 例子主要是对C:\\file目录下的文件的内容建立索引,将文件路径作为搜索内容的附属 */ if(file.isDirectory()){ String[] fileList = file.list(); for (int i = 0; i < fileList.length; i++){ //建立一个新的文档,它可以看作是数据库的一行记录 Document doc = new Document(); File f = new File(file, fileList[i]); Reader reader = new BufferedReader(new FileReader(f)); doc.add(new Field("file",reader));//为doument添加field doc.add(new Field("path",f.getAbsolutePath(),Field.Store.YES,Field.Index.NO)); writer.addDocument(doc); } } writer.close();//这一步是必须的,只有这样数据才会被写入索引的目录里 Date date2 = new Date(); System.out.println("用时"+(date2.getTime()-date1.getTime())+"毫秒"); }
注意:因为建立索引本来就是费时,所以说最后输出的用时会比较长,请不要奇怪。
b)一个通过索引来全文检索的例子 public void HelloSearch() throws IOException, ParseException{ //和上面的IndexWriter一样是一个工具 IndexSearcher indexSearcher = new IndexSearcher("c:\\index"); QueryParser queryParser = new QueryParser("file",new StandardAnalyzer()); //new StandardAnalyzer()这是一个分词器 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); //这个地方Query是抽象类大家也注意一下,下面会讲到的 Query query = queryParser.parse(br.readLine()); Hits hits = indexSearcher.search(query); Document doc = null; System.out.print("正搜索................"); for (int i = 0; i < hits.length(); i++){ doc = hits.doc(i); System.out.println("内容是:"+doc.get("file"));//注意这里输出的是什么 System.out.println("文件的路径是:" + doc.get("path")); } } 通过上面的两个例子应该可以看出Lucene还是比较简单的。
运行一下上面的两个例子,大家可能会说怎么doc.get(“file”);返回的是空呢,我们马上会讲到。
下面讲一下索引的建立
其实从上面的例子就可以看出建立索引就用到Document,IndexWriter,Field。 最简单的步骤就是:
首先分别new 一个Document,IndexWriter,Field,然后用Doument.add()方法加入Field.其次用IndexWrtier.addDocument()
方法加入Document。 最后调用一下IndexWriter.close()方法关闭输入索引,这一步非常的重要只有调用这个方法索引才会被
写入索引的目录里,而这是被很多初学的人所忽略的。 Document没有什么好介绍的,把它的作用看成数据库中的一行记录就行。
Field是一个比较重要的也是比较复杂的,看一下它的构造函数有5个:Field
(String
name, byte[] value, Field.Store
store) Field
(String
name, Reader
reader) Field
(String
name, Reader
reader, Field.TermVector
termVector)
Field (String name, String value, Field.Store store, Field.Index index)
Field (String name, String value, Field.Store store, Field.Index index, Field.TermVector termVector)
在Field中有三个内部类:Field.Index,Field.Store,Field.termVector,而构造函数也用到了它们。 注意:
termVector
是Lucene 1.4
新增的,它提供一种向量机制来进行模糊查询,这个不常用。它们的不同的组合,在全文检索
中有着不同的作用。看看下面的表吧:
Field.Index
|
Field.Store
|
说明
|
|
|
被分词索引且存储
|
|
|
被分词索引但不存储
|
|
|
这是不能被搜索的,它只是被搜索内容的附属物。如URL等
|
|
|
不被分词,它作为一个整体被搜索,搜一部分是搜不出来的
|
|
|
没有这种用法
|
而对于Field
(String
name, Reader
reader) Field
(String
name, Reader
reader, Field.TermVector
termVector)
他们是Field.Index.TOKENIZED和Field.Store.NO的。这就是为什么我们在上面的例子中会出现文章的内容为 null了。因为它只是被索引了,而并没有被存储下来。如果一定要看到文章的内容的话可以通过文章的路径得到。毕竟文章的路径是作为搜索的附属物被搜索出来了。而我们在Web开发的时候一般是将大数据放在数据库中,不会放在文件系统中,更不会放在索引目录里,因为它太大了操作会加大服务器的负担。
下面介绍一下IndexWriter:
它就是一个写入索引的写入器,它的任务比较简单:
1.用addDocument()将已经准备好写入索引的document们加入
2.调用close()将索引写入索引目录
先看一下它的构造函数: IndexWriter
(Directory
d, Analyzer
a, boolean create) IndexWriter
(File
path, Analyzer
a, boolean create) IndexWriter
(String
path, Analyzer
a, boolean create)
可见构造它需要一个索引文件目录,一个分析器(一般用标准的这个),最后一个参数是标识是否清空索引目录
它有一些设置参数的功能如:设置Field的最大长度
看个例子:
public void IndexMaxField() throws IOException { IndexWriter indexWriter= new IndexWriter("c:\\index",new StandardAnalyzer(),true); Document doc1 = new Document(); doc1.add(new Field("name1","程序员之家",Field.Store.YES,Field.Index.TOKENIZED)); Document doc2 = new Document(); doc2.add(new Field("name2","Welcome to the Home of programers",Field.Store.YES,Field.Index.TOKENIZED)); indexWriter.setMaxFieldLength(5); indexWriter.addDocument(doc1); indexWriter.setMaxFieldLength(3); indexWriter.addDocument(doc1); indexWriter.setMaxFieldLength(0); indexWriter.addDocument(doc2); indexWriter.setMaxFieldLength(3); indexWriter.addDocument(doc2); indexWriter.close(); } public void SearcherMaxField() throws ParseException, IOException { Query query = null; Hits hits = null; IndexSearcher indexSearcher= null; QueryParser queryParser= null; queryParser = new QueryParser("name1",new StandardAnalyzer()); query = queryParser.parse("程序员"); indexSearcher= new IndexSearcher("c:\\index"); hits = indexSearcher.search(query); System.out.println("您搜的是:程序员"); System.out.println("找到了"+hits.length()+"个结果"); System.out.println("它们分别是:"); for (int i = 0; i < hits.length(); i++){ Document doc = hits.doc(i); System.out.println(doc.get("name1")); } query = queryParser.parse("程序员之家"); indexSearcher= new IndexSearcher("c:\\index"); hits = indexSearcher.search(query); System.out.println("您搜的是:程序员之家"); System.out.println("找到了"+hits.length()+"个结果"); System.out.println("它们分别是:"); for (int i = 0; i < hits.length(); i++){ Document doc = hits.doc(i); System.out.println(doc.get("name1")); } queryParser = new QueryParser("name2",new StandardAnalyzer()); query = queryParser.parse("Welcome"); indexSearcher= new IndexSearcher("c:\\index"); hits = indexSearcher.search(query); System.out.println("您搜的是:Welcome"); System.out.println("找到了"+hits.length()+"个结果"); System.out.println("它们分别是:"); for (int i = 0; i < hits.length(); i++){ Document doc = hits.doc(i); System.out.println(doc.get("name2")); } query = queryParser.parse("the"); indexSearcher= new IndexSearcher("c:\\index"); hits = indexSearcher.search(query); System.out.println("您搜的是:the"); System.out.println("找到了"+hits.length()+"个结果"); System.out.println("它们分别是:"); for (int i = 0; i < hits.length(); i++){ Document doc = hits.doc(i); System.out.println(doc.get("name2")); } query = queryParser.parse("home"); indexSearcher= new IndexSearcher("c:\\index"); hits = indexSearcher.search(query); System.out.println("您搜的是:home"); System.out.println("找到了"+hits.length()+"个结果"); System.out.println("它们分别是:"); for (int i = 0; i < hits.length(); i++) { Document doc = hits.doc(i); System.out.println(doc.get("name2")); } }
总结一下:
1.设置Field的长度限制只是限制了搜索。如果用了Field.Store.YES的话还是会
全部被保存进索引目录里的。
2.为什么搜the没有搜出来呢?是因为lucene分析英文的时候不会搜索the to of 等无用的词(搜这些词是无意义的)。
3.New StandardAnlayzer()对于英文的分词是按空格和一些无用的词,而中文呢是全部的单个的字。
4.设置Field的最大长度是以0开头和数组一样。
大家还可以试一下别的,以便加深一下印象
到现在我们已经可以用lucene建立索引了
下面介绍一下几个功能来完善一下:
1.索引格式
其实索引目录有两种格式,一种是除配置文件外,每一个Document独立成为一个文件(这种搜索起来会影响速度)。另一种是全部Document成一个文件,这样属于复合模式就快了。
2.索引文件可放的位置:
索引可以存放在两个地方1.硬盘,2.内存。放在硬盘上可以用FSDirectory(),放在内存的用RAMDirectory()不过一关机就没了。
FSDirectory.getDirectory
(File
file, boolean create)
FSDirectory.getDirectory
(String path, boolean create)
两个工厂方法返回目录
New RAMDirectory()
就直接可以,再和IndexWriter
(Directory d, Analyzer a, boolean create)
一配合就行了
如:
IndexWrtier indexWriter = new IndexWriter(FSDirectory.getDirectory(“c:\\index”,true),new StandardAnlyazer(),true);
IndexWrtier indexWriter = new IndexWriter(new RAMDirectory(),new StandardAnlyazer(),true);
3.索引的合并
这个可用IndexWriter.addIndexes
(Directory[] dirs)
将目录加进去
来看个例子:
public void UniteIndex() throws IOException{ IndexWriter writerDisk = new IndexWriter(FSDirectory.getDirectory("c:\\indexDisk", true),new StandardAnalyzer(),true); Document docDisk = new Document(); docDisk.add(new Field("name","程序员之家",Field.Store.YES,Field.Index.TOKENIZED)); writerDisk.addDocument(docDisk); RAMDirectory ramDir = new RAMDirectory(); IndexWriter writerRam = new IndexWriter(ramDir,new StandardAnalyzer(),true); Document docRam = new Document(); docRam.add(new Field("name","程序员杂志",Field.Store.YES,Field.Index.TOKENIZED)); writerRam.addDocument(docRam); writerRam.close();//这个方法非常重要,是必须调用的 writerDisk.addIndexes(new Directory[]{ramDir}); writerDisk.close(); } public void UniteSearch() throws ParseException, IOException{ QueryParser queryParser = new QueryParser("name",new StandardAnalyzer()); Query query = queryParser.parse("程序员"); IndexSearcher indexSearcher =new IndexSearcher("c:\\indexDisk"); Hits hits = indexSearcher.search(query); System.out.println("找到了"+hits.length()+"结果"); for(int i=0;i< hits.length();i++){ Document doc = hits.doc(i); System.out.println(doc.get("name")); } } 这个例子是将内存中的索引合并到硬盘上来.
注意:合并的时候一定要将被合并的那一方的IndexWriter的close()方法调用。
4.对索引的其它操作:
IndexReader类是用来操作索引的,它有对Document,Field的删除等操作。
下面一部分的内容是:全文的搜索
全文的搜索主要是用:IndexSearcher,Query,Hits,Document(都是Query的子类),有的时候用QueryParser
主要步骤:
1.new QueryParser(Field字段,new 分析器)
2.Query query = QueryParser.parser(“要查询的字串”);这个地方我们可以用反射api看一下query究竟是什么类型
3.new IndexSearcher(索引目录).search(query);返回Hits
4.用Hits.doc(n);可以遍历出Document
5.用Document可得到Field的具体信息了。
其实1 ,2两步就是为了弄出个Query 实例,究竟是什么类型的看分析器了。
拿以前的例子来说吧
QueryParser queryParser = new QueryParser("name",new StandardAnalyzer());
Query query = queryParser.parse("程序员"); //这里返回的就是org.apache.lucene.search.PhraseQuery
IndexSearcher indexSearcher =new IndexSearcher("c:\\indexDisk");
Hits hits = indexSearcher.search(query);
不管是什么类型,无非返回的就是Query的子类,我们完全可以不用这两步直接new个Query的子类的实例就ok了,
不过一般还是用这两步因为它返回的是PhraseQuery这个是非常强大的query子类,它可以进行多字搜索。用QueryParser可以
设置各个关键字之间的关系这个是最常用的了。
IndexSearcher:
其实IndexSearcher它内部自带了一个IndexReader用来读取索引的,IndexSearcher有个close()方法,这个方法不是用
来关闭IndexSearcher的是用来关闭自带的IndexReader。
QueryParser呢可以用parser.setOperator()来设置各个关键字之间的关系,它可以自动通过空格从字串里面将关键字分离出来。
注意:用QueryParser搜索的时候分析器一定的和建立索引时候用的分析器是一样的。
Query:
可以看一个lucene2.0的帮助文档有很多的子类:
BooleanQuery, ConstantScoreQuery, ConstantScoreRangeQuery, DisjunctionMaxQuery, FilteredQuery,
MatchAllDocsQuery, MultiPhraseQuery, MultiTermQuery, PhraseQuery, PrefixQuery, RangeQuery, SpanQuery, TermQuery
各自有用法看一下文档就能知道它们的用法了
下面一部分讲一下lucene的分析器:
分析器是由分词器和过滤器组成的,拿英文来说吧分词器就是通过空格把单词分开,过滤器就是把the,to,of等词去掉不被搜索和索引。
我们最常用的是StandardAnalyzer()它是lucene的标准分析器它集成了内部的许多的分析器。
最后一部分了:lucene的高级搜索了
1.排序
Lucene有内置的排序用IndexSearcher.search(query,sort)但是功能并不理想。我们需要自己实现自定义的排序。
这样的话得实现两个接口: ScoreDocComparator, SortComparatorSource
用IndexSearcher.search(query,new Sort(new SortField(String Field,SortComparatorSource)));
就看个例子吧:
这是一个建立索引的例子:
public void IndexSort() throws IOException { IndexWriter writer = new IndexWriter("C:\\indexStore",new StandardAnalyzer(),true); Document doc = new Document(); doc.add(new Field("sort","1",Field.Store.YES,Field.Index.TOKENIZED)); writer.addDocument(doc); doc = new Document(); doc.add(new Field("sort","4",Field.Store.YES,Field.Index.TOKENIZED)); writer.addDocument(doc); doc = new Document(); doc.add(new Field("sort","3",Field.Store.YES,Field.Index.TOKENIZED)); writer.addDocument(doc); doc = new Document(); doc.add(new Field("sort","5",Field.Store.YES,Field.Index.TOKENIZED)); writer.addDocument(doc); doc = new Document(); doc.add(new Field("sort","9",Field.Store.YES,Field.Index.TOKENIZED)); writer.addDocument(doc); doc = new Document(); doc.add(new Field("sort","6",Field.Store.YES,Field.Index.TOKENIZED)); writer.addDocument(doc); doc = new Document(); doc.add(new Field("sort","7",Field.Store.YES,Field.Index.TOKENIZED)); writer.addDocument(doc); writer.close(); } 下面是搜索的例子: public void SearchSort1() throws IOException, ParseException { IndexSearcher indexSearcher = new IndexSearcher("C:\\indexStore"); QueryParser queryParser = new QueryParser("sort",new StandardAnalyzer()); Query query = queryParser.parse("4"); Hits hits = indexSearcher.search(query); System.out.println("有"+hits.length()+"个结果"); Document doc = hits.doc(0); System.out.println(doc.get("sort")); } public void SearchSort2() throws IOException, ParseException { IndexSearcher indexSearcher = new IndexSearcher("C:\\indexStore"); Query query = new RangeQuery(new Term("sort","1"),new Term("sort","9"),true); //这个地方前面没有提到,它是用于范围的Query可以看一下帮助文档. Hits hits = indexSearcher.search(query,new Sort(new SortField("sort",new MySortComparatorSource()))); System.out.println("有"+hits.length()+"个结果"); for(int i=0;i< hits.length();i++){ Document doc = hits.doc(i); System.out.println(doc.get("sort")); } } public class MyScoreDocComparator implements ScoreDocComparator { private Integer[]sort; public MyScoreDocComparator(String s,IndexReader reader, String fieldname) throws IOException{ sort = new Integer[reader.maxDoc()]; for(int i = 0;i< reader.maxDoc();i++){ Document doc =reader.document(i); sort[i]=new Integer(doc.get("sort")); } } public int compare(ScoreDoc i, ScoreDoc j){ if(sort[i.doc]>sort[j.doc]) return 1; if(sort[i.doc]< sort[j.doc]) return -1; return 0; } public int sortType(){ return SortField.INT; } public Comparable sortValue(ScoreDoc i){ // TODO 自动生成方法存根 return new Integer(sort[i.doc]); } } public class MySortComparatorSource implements SortComparatorSource { private static final long serialVersionUID = -9189690812107968361L; public ScoreDocComparator newComparator(IndexReader reader, String fieldname) throws IOException{ if(fieldname.equals("sort")) return new MyScoreDocComparator("sort",reader,fieldname); return null; } } SearchSort1()输出的结果没有排序,SearchSort2()就排序了。
2.多域搜索 MultiFieldQueryParser
1.如果想输入关键字而不想关心是在哪个Field里的就可以用MultiFieldQueryParser了。
用它的构造函数即可后面的和一个Field一样。
MultiFieldQueryParser. parse
(String
[] queries, String
[] fields, BooleanClause.Occur
[] flags, Analyzer
analyzer)
第三个参数比较特殊这里也是与以前lucene1.4.3不一样的地方,看一个例子就知道了。String[] fields = {"filename", "contents", "description"};
BooleanClause.Occur[] flags = {BooleanClause.Occur.SHOULD,
BooleanClause.Occur.MUST,//在这个Field里必须出现的
BooleanClause.Occur.MUST_NOT};//在这个Field里不能出现
MultiFieldQueryParser.parse("query", fields, flags, analyzer);
2.多索引搜索 MultiSearcher
在构造的时候传进去一个Searcher数组即可
3.过滤器Filter
看个例子:
public void FilterTest() throws IOException, ParseException { IndexWriter indexWriter = new IndexWriter("C:\\FilterTest",new StandardAnalyzer(),true); Document doc = new Document(); doc.add(new Field("name","程序员之家",Field.Store.YES,Field.Index.TOKENIZED)); indexWriter.addDocument(doc); doc=new Document(); doc.add(new Field("name","程序员杂志",Field.Store.YES,Field.Index.TOKENIZED)); indexWriter.addDocument(doc); indexWriter.close(); Query query = null; Hits hits = null; IndexSearcher indexSearcher = new IndexSearcher("C:\\FilterTest"); QueryParser queryParser = new QueryParser("name",new StandardAnalyzer()); query = queryParser.parse("程序"); hits = indexSearcher.search(query,new Filter(){ @Override public BitSet bits(IndexReader reader) throws IOException{ BitSet bit = new BitSet(reader.maxDoc()); for(int i=0;i< reader.maxDoc();i++){ if(reader.document(i).get("name").enth("杂志"))//将以“杂志”后缀的过滤掉 continue; bit.set(i);ks } return bit; } }); System.out.println(hits.length()); for(int i=0;i< hits.length();i++){ doc =hits.doc(i); System.out.println(doc.get("name")); } } 这只是一个入门的文档Lucene 2.0的内容还有很多,这里只是介绍了一部分,其它的可以看帮助文档来学习。
发表评论
-
类的初始化顺序---你真的明白吗???^_^
2007-11-13 17:09 712^_^基础知识,要是不很明白的就看看吧。^_^ public ... -
最重要的十几个J2EE 最佳实践
2007-01-06 09:25 689简介在过去的 5 年中,已经有许多人写了关于 J2E ... -
J2EE项目10大风险
2007-01-06 09:53 894当你开始着手组织一个 ... -
把java本地程序配置在windows服务来运行[转载]
2007-01-07 15:27 1115步骤如下: 0 ... -
JSP 2.0: The New Deal, Part 1 [转载]
2007-01-08 15:18 778期待已久的日子即将到来: 最新版 ... -
showDialog的JSP应用
2007-01-16 16:17 1886用于解决在一个页面上 ... -
showModalDialog和showModelessDialog使用心得
2007-01-20 13:23 849一、showModalDialog和showMod ... -
JBoss启动过程
2007-01-28 09:28 8421. o ... -
J2EE开发之常用开源项目介绍
2007-01-28 09:49 811主要就我所了解的J2EE开发的框 ... -
frame中隐藏横向滚动条
2007-01-28 17:50 2595在网吧客户端项目中使用了frame的方式,布局如下:遇到的问题 ... -
jsp生成html
2007-01-31 18:31 2181从网上找到了两种方法都是大同小异,经过 ... -
编写你自己的单点登录(SSO)服务
2007-02-01 15:06 1201摘要 ... -
HttpClient入门
2007-02-01 15:07 789HttpClient 是 Apache Jakarta Com ... -
跨domain的SSO
2007-02-01 15:31 915在我写了SSO的文章以后,有几个网友希望我能提一提跨domai ... -
jfreechart例子
2007-02-07 10:44 4169一、饼图<%@ page language=" ... -
JSP避免Form重复提交的三种方案
2007-02-12 08:57 8871、javascript ,设置一个变量,只允许提交一次。 ... -
flash对联广告
2007-02-14 16:35 759<html><head></he ... -
什么是Portlet ?
2007-03-09 08:37 944作者:Sunil Patil; observer ... -
在J道上看到的:RoR可否替代J2EE?
2007-03-17 14:40 1226... -
[转载]session详解
2007-03-21 08:36 822這篇文 ...
相关推荐
全面好用的lucene 2.0 api以及lucene 3.0 api帮助文档
开发自己的搜索引擎《lucene2.0+heritrix》一书对应的源码资料,总共有30M,只上传了几个例子. ch2-lucene入门小例子 myReserch-可用的网络搜索引擎
本软件是开发自己的搜索引擎《lucene2.0+heritrix》一书对应的源码资料,不过由于代码很大,只发布其中最全的部分,各章的源码就不发了。
lucene java 搜索引擎 比较经典的全文搜索引擎,最近发现在官方网站上找不到了,放在这里给大家,方便点,多谢谢支持!
这是Lucene 2.0+Heriterx书源代码里ch7文件夹下的lib文件,里面都是ch7项目里jar包,Lucene 2.0+Heriterx书源代码-ch7lib
自己学习Lucenes 2.0 和Heritrix之后的总结
Lucene2.0+Heritrix搜索引擎 随书光盘
lucene 2.0虽然是比较老的技术,它对实时搜索支持交差,不过很多普通的搜索引擎对实时性要求并不是很高,并且对于分词上没有太多的个性化专业要求,那么这个选择将是非常好的,提供各类分词接口、存储接口、索引接口...
【别下这个哈,,】 【完整版的在】《开发自己的搜索引擎-Lucene 2.0 Heritrix》 http://download.csdn.net/source/1756566 文件大小:24.60 MB
Lucene2.0+Heritrix(ch3源代码)
Lucene2.0+Nutch0.8 API帮助文档,以前每次查看他们的API都得通过他们的网站去获取,实在麻烦。功夫不负有心人,通过自己的努力终于获得他们CHM格式的API,现在拿来跟大家分享一下
lucene2.0+heritrix的随书光盘,有很多好用的lucene实例,还包括一个完整的垂直搜索引擎的设计
【完整光盘24.5M】开发自己的搜索引擎-Lucene 2.0+Heritrix.zip 评论+评分后即可返回1分。。O(∩_∩)O 。。谢谢支持。。
开发自己的搜索引擎--Lucene 2.0+Heritrix(爬虫)第10章
去下载这个吧。(完整版的) http://d.download.csdn.net/down/1756566/caizhongda Lucene2.0+Heritrix搜索引擎(完整光盘).part2.rar
Lucene是apache组织的一个用java实现全文搜索引擎的开源项目。其功能非常的强大,api也很简单。总得来说用Lucene来进行建立和搜索和操作数据库是差不多的,Document可以看作是数据库的一行记录,Field可以看作是...
Lucene.2.0的API文档合集 是从html装成chm的
lucene-2.0开发专用
Lucene Heritrix 搜索 Lucene Heritrix csdn