Lucene初级教程.doc
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Lucene 初级教程
- 资源描述:
-
Lucene初级教程 2007-12-26 15:24 点击次数:0 次 1 lucene简介 1.1 什么是lucene Lucene是一个全文搜索框架,而不是应用产品。因此它并不像 或者google Desktop那么拿来就能用,它只是提供了一种工具让你能实现这些产品。 2 lucene的工作方式 lucene提供的服务实际包含两部分:一入一出。所谓入是写入,即将你提供的源(本质是字符串)写入索引或者将其从索引中删除;所谓出是读出,即向用户提供全文搜索服务,让用户可以通过关键词定位源。 2.1写入流程 源字符串首先经过analyzer处理,包括:分词,分成一个个单词;去除stopword(可选)。 将源中需要的信息加入Document的各个Field中,并把需要索引的Field索引起来,把需要存储的Field存储起来。 将索引写入存储器,存储器可以是内存或磁盘。 2.2读出流程 用户提供搜索关键词,经过analyzer处理。 对处理后的关键词搜索索引找出对应的Document。 用户根据需要从找到的Document中提取需要的Field。 3 一些需要知道的概念 3.1 analyzer Analyzer是分析器,它的作用是把一个字符串按某种规则划分成一个个词语,并去除其中的无效词语,这里说的无效词语是指英文中的“of”、“the”,中文中的“的”、“地”等词语,这些词语在文章中大量出现,但是本身不包含什么关键信息,去掉有利于缩小索引文件、提高效率、提高命中率。 分词的规则千变万化,但目的只有一个:按语义划分。这点在英文中比较容易实现,因为英文本身就是以单词为单位的,已经用空格分开;而中文则必须以某种方法将连成一片的句子划分成一个个词语。具体划分方法下面再详细介绍,这里只需了解分析器的概念即可。 3.2 document 用户提供的源是一条条记录,它们可以是文本文件、字符串或者数据库表的一条记录等等。一条记录经过索引之后,就是以一个Document的形式存储在索引文件中的。用户进行搜索,也是以Document列表的形式返回。 3.3 field 一个Document可以包含多个信息域,例如一篇文章可以包含“标题”、“正文”、“最后修改时间”等信息域,这些信息域就是通过Field在Document中存储的。 Field有两个属性可选:存储和索引。通过存储属性你可以控制是否对这个Field进行存储;通过索引属性你可以控制是否对该Field进行索引。这看起来似乎有些废话,事实上对这两个属性的正确组合很重要,下面举例说明:还是以刚才的文章为例子,我们需要对标题和正文进行全文搜索,所以我们要把索引属性设置为真,同时我们希望能直接从搜索结果中提取文章标题,所以我们把标题域的存储属性设置为真,但是由于正文域太大了,我们为了缩小索引文件大小,将正文域的存储属性设置为假,当需要时再直接读取文件;我们只是希望能从搜索解果中提取最后修改时间,不需要对它进行搜索,所以我们把最后修改时间域的存储属性设置为真,索引属性设置为假。上面的三个域涵盖了两个属性的三种组合,还有一种全为假的没有用到,事实上Field不允许你那么设置,因为既不存储又不索引的域是没有意义的。 3.4 term term是搜索的最小单位,它表示文档的一个词语,term由两部分组成:它表示的词语和这个词语所出现的field。 3.5 tocken tocken是term的一次出现,它包含trem文本和相应的起止偏移,以及一个类型字符串。一句话中可以出现多次相同的词语,它们都用同一个term表示,但是用不同的tocken,每个tocken标记该词语出现的地方。 3.6 segment 添加索引时并不是每个document都马上添加到同一个索引文件,它们首先被写入到不同的小文件,然后再合并成一个大索引文件,这里每个小文件都是一个segment。 4 如何建索引 4.1 最简单的能完成索引的代码片断 IndexWriter writer = new IndexWriter(“/data/index/”, new StandardAnalyzer(), true); Document doc = new Document(); doc.add(new Field("title", "lucene introduction", Field.Store.YES, Field.Index.TOKENIZED)); doc.add(new Field("content", "lucene works well", Field.Store.YES, Field.Index.TOKENIZED)); writer.addDocument(doc); writer.optimize(); writer.close(); 下面我们分析一下这段代码。 首先我们创建了一个writer,并指定存放索引的目录为“/data/index”,使用的分析器为StandardAnalyzer,第三个参数说明如果已经有索引文件在索引目录下,我们将覆盖它们。然后我们新建一个document。 我们向document添加一个field,名字是“title”,内容是“lucene introduction”,对它进行存储并索引。再添加一个名字是“content”的field,内容是“lucene works well”,也是存储并索引。 然后我们将这个文档添加到索引中,如果有多个文档,可以重复上面的操作,创建document并添加。 添加完所有document,我们对索引进行优化,优化主要是将多个segment合并到一个,有利于提高索引速度。 随后将writer关闭,这点很重要。 对,创建索引就这么简单! 当然你可能修改上面的代码获得更具个性化的服务。 4.2 索引文本文件 如果你想把纯文本文件索引起来,而不想自己将它们读入字符串创建field,你可以用下面的代码创建field: Field field = new Field("content", new FileReader(file)); 这里的file就是该文本文件。该构造函数实际上是读去文件内容,并对其进行索引,但不存储。 Lucene 2 教程 Lucene是apache组织的一个用java实现全文搜索引擎的开源项目。 其功能非常的强大,api也很简单。总得来说用Lucene来进行建立 和搜索和操作数据库是差不多的(有点像),Document可以看作是 数据库的一行记录,Field可以看作是数据库的字段。用lucene实 现搜索引擎就像用JDBC实现连接数据库一样简单。 Lucene2.0,它与以前广泛应用和介绍的Lucene 1.4.3并不兼容。 Lucene2.0的下载地址是http://apache.justdn.org/lucene/java/ 例子一 : 1、在windows系统下的的C盘,建一个名叫s的文件夹,在该文件夹里面随便建三个txt文件,随便起名啦,就叫"1.txt","2.txt"和"3.txt"啦 其中1.txt的内容如下: 中华人民共和国 全国人民 2006年 而"2.txt"和"3.txt"的内容也可以随便写几写,这里懒写,就复制一个和1.txt文件的内容一样吧 2、下载lucene包,放在classpath路径中 建立索引: package ; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.Date; 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.index.IndexWriter; /** */ /** * author lighter date 2006-8-7 */ public class TextFileIndexer { public static void main(String[] args) throws Exception { /**/ /* 指明要索引文件夹的位置,这里是C盘的S文件夹下 */ File fileDir = new File( " c:\\s " ); /**/ /* 这里放索引文件的位置 */ File indexDir = new File( " c:\\index " ); Analyzer luceneAnalyzer = new StandardAnalyzer(); IndexWriter indexWriter = new IndexWriter(indexDir, luceneAnalyzer, true ); File[] textFiles = fileDir.listFiles(); long startTime = new Date().getTime(); // 增加document到索引去 for ( int i = 0 ; i < textFiles.length; i ++ ) { if (textFiles[i].isFile() && textFiles[i].getName().endsWith( " .txt " )) { System.out.println( " File " + textFiles[i].getCanonicalPath() + " 正在被索引. " ); String temp = FileReaderAll(textFiles[i].getCanonicalPath(), " GBK " ); System.out.println(temp); Document document = new Document(); Field FieldPath = new Field( " path " , textFiles[i].getPath(), Field.Store.YES, Field.Index.NO); Field FieldBody = new Field( " body " , temp, Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.WITH_POSITIONS_OFFSETS); document.add(FieldPath); document.add(FieldBody); indexWriter.addDocument(document); } } // optimize()方法是对索引进行优化 indexWriter.optimize(); indexWriter.close(); // 测试一下索引的时间 long endTime = new Date().getTime(); System.out .println( " 这花费了 " + (endTime - startTime) + " 毫秒来把文档增加到索引里面去! " + fileDir.getPath()); } public static String FileReaderAll(String FileName, String charset) throws IOException { BufferedReader reader = new BufferedReader( new InputStreamReader( new FileInputStream(FileName), charset)); String line = new String(); String temp = new String(); while ((line = reader.readLine()) != null ) { temp += line; } reader.close(); return temp; } } 索引的结果: File C:\s\ 1 .txt正在被索引. 中华人民共和国全国人民2006年 File C:\s\ 2 .txt正在被索引. 中华人民共和国全国人民2006年 File C:\s\ 3 .txt正在被索引. 中华人民共和国全国人民2006年 这花费了297 毫秒来把文档增加到索引里面去 ! c:\s 3、建立了索引之后,查询啦.... package ; import java.io.IOException; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.queryParser.ParseException; import org.apache.lucene.queryParser.QueryParser; import org.apache.lucene.search.Hits; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; public class TestQuery { public static void main(String[] args) throws IOException, ParseException { Hits hits = null ; String queryString = " 中华 " ; Query query = null ; IndexSearcher searcher = new IndexSearcher( " c:\\index " ); Analyzer analyzer = new StandardAnalyzer(); try { QueryParser qp = new QueryParser( " body " , analyzer); query = qp.parse(queryString); } catch (ParseException e) { } if (searcher != null ) { hits = searcher.search(query); if (hits.length() > 0 ) { System.out.println( " 找到: " + hits.length() + " 个结果! " ); } } } } 其运行结果: 找到: 3 个结果 ! Lucene 其实很简单的,它最主要就是做两件事:建立索引和进行搜索 来看一些在lucene中使用的术语,这里并不打算作详细的介绍,只是点一下而已----因为这一个世界有一种好东西,叫搜索。 IndexWriter:lucene中最重要的的类之一,它主要是用来将文档加入索引,同时控制索引过程中的一些参数使用。 Analyzer:分析器,主要用于分析搜索引擎遇到的各种文本。常用的有StandardAnalyzer分析器,StopAnalyzer分析器,WhitespaceAnalyzer分析器等。 Directory:索引存放的位置;lucene提供了两种索引存放的位置,一种是磁盘,一种是内存。一般情况将索引放在磁盘上;相应地lucene提供了FSDirectory和RAMDirectory两个类。 Document:文档;Document相当于一个要进行索引的单元,任何可以想要被索引的文件都必须转化为Document对象才能进行索引。 Field:字段。 IndexSearcher:是lucene中最基本的检索工具,所有的检索都会用到IndexSearcher工具; Query:查询,lucene中支持模糊查询,语义查询,短语查询,组合查询等等,如有TermQuery,BooleanQuery,RangeQuery,WildcardQuery等一些类。 QueryParser: 是一个解析用户输入的工具,可以通过扫描用户输入的字符串,生成Query对象。 Hits:在搜索完成之后,需要把搜索结果返回并显示给用户,只有这样才算是完成搜索的目的。在lucene中,搜索的结果的集合是用Hits类的实例来表示的。 上面作了一大堆名词解释,下面就看几个简单的实例吧: 1、简单的的StandardAnalyzer测试例子 package ; import java.io.IOException; import java.io.StringReader; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.Token; import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.standard.StandardAnalyzer; public class StandardAnalyzerTest { // 构造函数, public StandardAnalyzerTest() { } public static void main(String[] args) { // 生成一个StandardAnalyzer对象 Analyzer aAnalyzer = new StandardAnalyzer(); // 测试字符串 StringReader sr = new StringReader( " lighter javaeye com is the are on " ); // 生成TokenStream对象 TokenStream ts = aAnalyzer.tokenStream( " name " , sr); try { int i = 0 ; Token t = ts.next(); while (t != null ) { // 辅助输出时显示行号 i ++ ; // 输出处理后的字符 System.out.println( " 第 " + i + " 行: " + t.termText()); // 取得下一个字符 t = ts.next(); } } catch (IOException e) { e.printStackTrace(); } } } 显示结果: 第1行:lighter 第2行:javaeye 第3行:com 提示一下: StandardAnalyzer是lucene中内置的"标准分析器",可以做如下功能: 1、对原有句子按照空格进行了分词 2、所有的大写字母都可以能转换为小写的字母 3、可以去掉一些没有用处的单词,例如"is","the","are"等单词,也删除了所有的标点 查看一下结果与"new StringReader("lighter javaeye com is the are on")"作一个比较就清楚明了。 这里不对其API进行解释了,具体见lucene的官方文档。需要注意一点,这里的代码使用的是lucene2的API,与1.43版有一些明显的差别。 2、看另一个实例,简单地建立索引,进行搜索 package ; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.queryParser.QueryParser; import org.apache.lucene.search.Hits; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.store.FSDirectory; public class FSDirectoryTest { // 建立索引的路径 public static final String path = " c:\\index2 " ; public static void main(String[] args) throws Exception { Document doc1 = new Document(); doc1.add( new Field( " name " , " lighter javaeye com " ,Field.Store.YES,Field.Index.TOKENIZED)); Document doc2 = new Document(); doc2.add( new Field( " name " , " lighter blog " ,Field.Store.YES,Field.Index.TOKENIZED)); IndexWriter writer = new IndexWriter(FSDirectory.getDirectory(path, true ), new StandardAnalyzer(), true ); writer.setMaxFieldLength( 3 ); writer.addDocument(doc1); writer.setMaxFieldLength( 3 ); writer.addDocument(doc2); writer.close(); IndexSearcher searcher = new IndexSearcher(path); Hits hits = null ; Query query = null ; QueryParser qp = new QueryParser( " name " , new StandardAnalyzer()); query = qp.parse( " lighter " ); hits = searcher.search(query); System.out.println( " 查找\ " lighter\ " 共 " + hits.length() + " 个结果 " ); query = qp.parse( " javaeye " ); hits = searcher.search(query); System.out.println( " 查找\ " javaeye\ " 共 " + hits.length() + " 个结果 " ); } } 运行结果: 查找 " lighter " 共2个结果 查找 " javaeye " 共1个结果 到现在我们已经可以用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 { Document doc = hits.doc(i); System.out.println(doc.get( " name " )); } } 这个例子是将内存中的索引合并到硬盘上来. 注意:合并的时候一定要将被合并的那一方的IndexWriter的close()方法调用。 4.对索引的其它操作: IndexReader类是用来操作索引的,它有对Document,Field的删除等操作。 下面一部分的内容是:全文的展开阅读全文
咨信网温馨提示:1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。
3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前可先查看【教您几个在下载文档中可以更好的避免被坑】。
5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
6、文档遇到问题,请及时联系平台进行协调解决,联系【微信客服】、【QQ客服】,若有其他问题请点击或扫码反馈【服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【版权申诉】”,意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:0574-28810668;投诉电话:18658249818。




Lucene初级教程.doc



实名认证













自信AI助手
















微信客服
客服QQ
发送邮件
意见反馈



链接地址:https://www.zixin.com.cn/doc/7696705.html