相信很多人都听过lucene,这样一个用于实现搜索引擎功能的一个工具包。说它是一个工具包,因为它只是提供我们用于索引和查询的工具,并不包含真正一个搜索引擎需要的其他东西——爬虫,抽取等等。
废话不多说,我们直接来看看lucene4的一些简单的例子(lucene4.1已经出了,暂时没来得及看有什么变化,lucene的API经常修改,所以版本间可能会有些不同的,大家需要注意):
还是给下lucene的下载地址,有些朋友喜欢用百度的,但那家伙太坑人了,很多外国网站没的。下载地址如下:http://archive.apache.org/dist/lucene/java/4.0.0/
下载后,我们可以看到有一堆的文件夹,首先demo里面当然就是例子了,这个不多说。看看还是有好处的。
我们经常使用的无非是下面几个:queryparser,analysis,core(核心,显然是必须的了),queries,其他的貌似比较少用到,除非你进行比较深入的定制,可能会用到suggest(建议方面的东西),其他的因为我暂时没接触到,就不在这里误人子弟了,以后有机会再学习。
好,接下来来点干货了。我在例子中用到的包有analysis,queryparser,core,另外的暂没有使用。说到底是一个索引工具包,首先当然是建立索引啦,
比如我现在在ubuntu下,我的eclipse目录是/opt/programs/eclipse,我要索引它里面的所有文件的文件名,放在一个名叫fileName的field里面。
在看代码前,我们先来了解一下lucene索引的结构:
一个索引是由无数多个doc组成的,而doc也是由无数多个field组成的。举个比较符合生活的例子:我们可以把一个索引想像成一本书,而doc则是每一本书的第一篇文章,而field则是每一篇文章里面的词语,词组,我们就是通过词组去找到那篇文章。(当然,说根据词组等去找一篇文章不太可行,我们可以把词语换成标题,每一篇文章的标题,这样肯定可以找到对应的文章的。)
进行lucene检索的情况就是查找field,如果找到对应的,则把该doc取出来,作为我们查询出来的结果。
1)首先我们看看索引情况:
package com.shun.lucene.simple; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.TextField; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexWriterConfig; import org.apache.lucene.index.IndexWriterConfig.OpenMode; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; import org.apache.lucene.util.Version; public class IndexAllFiles { public static void main(String[] args) { Directory dir = null; IndexWriter indexWriter = null; Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_40); try { dir = FSDirectory.open(new File("allFiles")); IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_40,analyzer); /* * 如果索引存在的情况下,我们采取什么样的策略 * 这里我们使用的是:存在的情况下新增 * 不存在的情况下创建 * 这符合我们一般的使用规则 */ iwc.setOpenMode(OpenMode.CREATE); indexWriter = new IndexWriter(dir,iwc); File file = new File("/opt/programs/eclipse"); System.out.println("Starting analyze fileNames...Please wait..."); List<String> fileNameList = checkAllFile(file); System.out.println("Ending analyze fileNames..."); for (String fileName:fileNameList) { /* * field就是lucene里面的最小单位了,一个索引里面可以有一大堆Document,而一个document里面可以有很多field * 这跟文章类似,一本书里面有很多篇文章,而一篇文章里面可以有很多单词,词组等。 */ Document doc = new Document(); Field field = new Field("fileName",fileName.toString(),TextField.TYPE_STORED); doc.add(field); indexWriter.addDocument(doc); } System.out.println("Writing index to file"); System.out.println("Finish indexing"); } catch (IOException e) { e.printStackTrace(); } finally { try { indexWriter.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * 此方法只是循环列出所传入的文件夹下的所有文件列表 * @param dir * @return */ private static List<String> checkAllFile(File dir) { List<String> fileNameList = new ArrayList<String>(); //不是目录的话里面肯定没文件了,我们在下面直接添加该文件到列表就OK了 if (dir.isDirectory()) { for (File file:dir.listFiles()) { //由于我在linux下,并且当前运行eclipse的用户非root,会有权限的问题,所以我这里加了一个判断是否可读 //正常情况下在windows上不需要,只需要判断是否是目录,然后递归调用即可。 if(file.isDirectory() && file.canRead()) { fileNameList.addAll(checkAllFile(file)); } else { fileNameList.add(file.getName()); } } } else { fileNameList.add(dir.getName()); } return fileNameList; } }相信注释已经够清楚了吧。
这里有个地方需要解释下:
for (String fileName:fileNameList) { /* * field就是lucene里面的最小单位了,一个索引里面可以有一大堆Document,而一个document里面可以有很多field * 这跟文章类似,一本书里面有很多篇文章,而一篇文章里面可以有很多单词,词组等。 */ Document doc = new Document(); Field field = new Field("fileName",fileName.toString(),TextField.TYPE_STORED); doc.add(field); indexWriter.addDocument(doc); }
我们这里是通过多个doc来添加的,注意,我们频繁的addDocument可能效率不高,我们其实可以把所有的fileName放在一个doc里面,doc并不像我们的map,它不会合并相同的名称的field的。我们稍后来看看这种情况。
2)有了索引之后,我们肯定就是需要在索引当中找我们需要的东西了。我们搜索一个eclipse这个单词,当然,我们前面只有一个fileName这个field,没有其他的,也只能查那一个了。
package com.shun.lucene.simple; import java.io.File; import java.io.IOException; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.index.DirectoryReader; import org.apache.lucene.queryparser.classic.ParseException; import org.apache.lucene.queryparser.classic.QueryParser; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.TopDocs; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; import org.apache.lucene.util.Version; public class ReadFromIndex { public static void main(String[] args) { Directory dir = null; Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_40); try { //这里打开的当然就是我们之前建立的索引文件夹了 dir = FSDirectory.open(new File("allFiles")); //DirectoryReader这个是lucene的一个工具类,在以前的IndexSearcher里面,貌似不用使用这个 IndexSearcher searcher = new IndexSearcher(DirectoryReader.open(dir)); QueryParser parser = new QueryParser(Version.LUCENE_40,"fileName",analyzer); Query query = parser.parse("eclipse"); TopDocs topDocs = searcher.search(query, 10); System.out.println("找到结果数:"+topDocs.totalHits); for (ScoreDoc scoreDoc:topDocs.scoreDocs) { System.out.println(searcher.doc(scoreDoc.doc).get("fileName")); } } catch (IOException e) { e.printStackTrace(); } catch (ParseException e) { e.printStackTrace(); } } }
我们可以看到,查询很简单,只是指定一个索引所在目录,然后来个IndexSearcher,再结合几个QueryParser和Query,然后就搞定了。
结果就不截图了,大家私下去运行下。我们来看看索引里面的内容,这里又涉及到另外的工具了,luke,这个是用于看索引的工具,可以到这里去下载:http://code.google.com/p/luke/downloads/list。但到了4.0.0alpha就没更新好久了,好在alpha对4.0的正式版还能用。
我们打开我们的索引,可以看到doc的内容:
在这里,我们可以看到doc的数量,2835,还有doc里面的field名称和value,另外的IdfXXX和Norm这个大家有兴趣自己可以去研究,是lucene的一些属性信息,包含是否索引、分词等等。
这里,我们是通过多个doc来添加的,我们上面说了,其他我们完全可以把多个field添加到同一个doc里面,虽然同一个fielName,但无所谓,因为索引并不是map形式的,不会覆盖相应的值。
我们回到上面的创建索引的例子,我们把循环的代码修改如下:
Document doc = new Document(); for (String fileName:fileNameList) { /* * field就是lucene里面的最小单位了,一个索引里面可以有一大堆Document,而一个document里面可以有很多field * 这跟文章类似,一本书里面有很多篇文章,而一篇文章里面可以有很多单词,词组等。 */ Field field = new Field("fileName",fileName.toString(),TextField.TYPE_STORED); doc.add(field); } indexWriter.addDocument(doc);
我们把Document提出去了,并且只在最后的时候来一个addDocument,添加到indexWriter中去。这里,我们可以点击luke的File->Re-open current index来重新打开当前的索引。我们可以看到:
我们可以看到,doc只剩一个了,而里面的fileName却有一大堆了。
当然,我们在一个doc里面添加了多个同样名字的filedName之后,在检索的时候通过searcher.doc(scoreDoc.doc).get("xxx")这样取出来的只能是第一个了,我们可以换成getValues("xxx")这样就可以取出数组,再进行遍历。
相关推荐
lucene提供的服务实际包含两部分:一入一出。所谓入是写入,即将你提供的源(本质是字符串)写入索引或者将其从索引中删除;所谓出是读出,即向用户提供全文搜索服务,让用户可以通过关键词定位源。 2.1写入流程 ...
对于Java开发者来说,这通常可以通过Eclipse、IntelliJ IDEA等IDE工具完成,或者手动将JAR包放入项目的lib目录下,并在构建脚本(如Maven或Gradle)中添加依赖。确保正确导入所有必要的JAR包至关重要,因为Lucene的...
Lucene是中国大百科全书式的全文检索库,它在Java世界中扮演着核心角色,为开发者提供了强大的...总之,Lucene是一个强大且灵活的全文检索工具,通过这个入门小例子,你可以逐步揭开其神秘的面纱,踏入文本搜索的世界。
假设我们创建了名为“luceneDemo”的目录,位于“E:\Lucene”下,并在该目录中放入了一些.txt格式的文档。 接下来,打开命令行界面(DOS),切换到“E:\Lucene”目录下,执行以下命令: ``` java org.apache....
例如,当合并因子为b时,每当栈顶有b个大小为size的索引时,就将它们合并为一个新索引并推入栈中。这个过程可以直观地分为几个步骤,如添加文档、检查是否需要合并、执行合并等。通过这种方式,Lucene可以有效地管理...
将Lucene.Net组件放入ASP.NET项目的Bin目录下,可以方便地通过引用该DLL来集成全文搜索功能。ASP.NET的事件驱动模型与Lucene.Net的异步处理机制相得益彰,可以实现高效且无阻塞的搜索服务。 总结来说,Lucene.Net ...
开发者可以通过API接口,轻松地将新数据接入到Zoie系统,实现近实时索引。 总结来说,结合Lucene 5的优秀搜索性能和Zoie的实时索引能力,我们可以构建出一个既能处理大规模数据,又能实现实时更新的搜索引擎。这种...
《Lucene 4.8 全文检索引擎入门详解》 Lucene 是一款开源的全文检索库,由 ...通过理解其核心组件和工作流程,以及实践简单的索引创建和查询操作,你就能迈入 Lucene 的世界,进一步探索和应用其高级特性和优化技巧。
4. 分词处理:在索引文档时,先用庖丁分词器对中文文本进行分词,然后将分词结果转换成Lucene的Term对象,再添加到索引中。 5. 搜索优化:在搜索阶段,同样可以使用庖丁分词器对用户输入的查询进行预处理,提高搜索...
- 将下载的Lucene JAR文件放入Tomcat的`lib`目录下。这使得Lucene库对所有部署在Tomcat中的应用都可见。 - 修改`$CATALINA_HOME/conf/server.xml`文件,为你的应用创建一个新的Context,例如: ```xml ...
其设计目标是提供一个可以方便地在Lucene、Solr等项目中快速接入的中文分词组件。IKAnalyzer支持热更新词典,能够动态添加或删除词汇,这在处理新词汇或者特殊领域词汇时非常有用。 集成IKAnalyzer到Lucene 4.5的...
- `QueryParser`调用`parser`进行语法分析,形成查询语法树,并放入`Query`对象中。 - `IndexSearcher`调用`search`方法对查询语法树`Query`进行搜索,得到结果`TopScoreDocCollector`。 #### 二、代码示例 ####...
一种常见的多线程策略是使用工作队列(如Java的`ExecutorService`),将待索引的文档放入队列,然后由多个工作线程从队列中取出文档,通过`IndexWriter`进行索引。这种方式可以避免线程间的直接竞争,同时利用多核...
在lucene搜索分页过程中,可以有两种方式 一种是将搜索结果集直接放到session中,但是假如结果集非常大,同时又存在大并发访问的时候,很可能造成服务器的内存不足,而使服务器宕机 还有一种是每次都重新进行搜索,这样...
lucene自带的中文分词器,将jar放入编译路径即可使用
Paoding这个名字来源于中国古代的一种宰牛技术,寓意其对中文文本的“解构”能力,如同庖丁解牛般精细入微。 Paoding的核心特点包括: 1. **智能词典**:Paoding使用了一种动态加载的词典机制,能够根据上下文信息...
- 将分析后的数据放入Document对象中,每个字段(Field)可以设置存储和索引属性。 - 将Document写入索引存储,存储介质可以是内存或磁盘。 2. **读出流程**: - 用户输入关键词,同样经过Analyzer处理。 - ...
### Java大数据内容_7Flume、Kafka、Sqoop、Lucene #### 一、Flume 入门 ##### 1.1 Flume 概述 Flume 是一个分布式的、可靠的、高可用的日志采集系统,主要用于收集、汇总和移动大量的日志数据。它由 Cloudera ...