【Lucene4.8教程之二】索引 2014-06-16 11:30 3845人阅读 评论(0) 收藏
一、基础内容
0、官方文档说明
(1)org.apache.lucene.index provides two primary classes:
IndexWriter, which creates and adds documents to indices; and
IndexReader, which accesses the data in the index.
(2)涉及的两个主要包有:
org.apache.lucene.index:Code to maintain and access indices.
org.apache.lucene.document:Thelogical representation of a Document for indexing and searching.
1、创建一个索引时,涉及的重要类有以下几个:
(1)IndexWriter:索引过程中的核心组件,用于创建新索引或者打开已有索引,以及向索引中添加、删除、更新被索引文档的信息。
(2)Document:代表一些域(field)的集合。
(3)Field及其子类:一个域,如文档创建时间,作者,内容等。
(4)Analyzer:分析器。
(5)Directory:可用于描述Lucene索引的存放位置。
2、索引文档的基本步骤如下:
(1)创建索引库IndexWriter
(2)根据文件创建文档Document
(3)向索引库中写入文档内容
基本程序如下:
package org.jediael.search.index; import java.io.File;
import java.io.FileReader;
import java.io.IOException; import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.LongField;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.jediael.util.LoadProperties; // 1、创建索引库IndexWriter
// 2、根据文件创建文档Document
// 3、向索引库中写入文档内容 public class IndexFiles { private IndexWriter writer = null; public void indexAllFileinDirectory(String indexPath, String docsPath)
throws IOException {
// 获取放置待索引文件的位置,若传入参数为空,则读取search.properties中设置的默认值。
if (docsPath == null) {
docsPath = LoadProperties.getProperties("docsDir");
}
final File docDir = new File(docsPath);
if (!docDir.exists() || !docDir.canRead()) {
System.out
.println("Document directory '"
+ docDir.getAbsolutePath()
+ "' does not exist or is not readable, please check the path");
System.exit(1);
} // 获取放置索引文件的位置,若传入参数为空,则读取search.properties中设置的默认值。
if (indexPath == null) {
indexPath = LoadProperties.getProperties("indexDir");
}
final File indexDir = new File(indexPath);
if (!indexDir.exists() || !indexDir.canRead()) {
System.out
.println("Document directory '"
+ indexDir.getAbsolutePath()
+ "' does not exist or is not readable, please check the path");
System.exit(1);
} try {
// 1、创建索引库IndexWriter
if(writer == null){
initialIndexWriter(indexDir);
}
index(writer, docDir);
} catch (IOException e) {
e.printStackTrace();
} finally{
writer.close();
}
} //使用了最简单的单例模式,用于返回一个唯一的IndexWirter,注意此处非线程安全,需要进一步优化。
private void initialIndexWriter(File indexDir) throws IOException { Directory returnIndexDir = FSDirectory.open(indexDir);
IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_48,new StandardAnalyzer(Version.LUCENE_48));
writer = new IndexWriter(returnIndexDir, iwc); } private void index(IndexWriter writer, File filetoIndex) throws IOException { if (filetoIndex.isDirectory()) {
String[] files = filetoIndex.list();
if (files != null) {
for (int i = 0; i < files.length; i++) {
index(writer, new File(filetoIndex, files[i]));
}
}
} else {
// 2、根据文件创建文档Document,考虑一下能否不用每次创建Document对象
Document doc = new Document();
Field pathField = new StringField("path", filetoIndex.getPath(),
Field.Store.YES);
doc.add(pathField);
doc.add(new LongField("modified", filetoIndex.lastModified(),
Field.Store.YES));
doc.add(new StringField("title",filetoIndex.getName(),Field.Store.YES));
doc.add(new TextField("contents", new FileReader(filetoIndex)));
//System.out.println("Indexing " + filetoIndex.getName()); // 3、向索引库中写入文档内容
writer.addDocument(doc);
}
}
}
一些说明:
(1)使用了最简单的单例模式,用于返回一个唯一的IndexWirter,注意此处非线程安全,需要进一步优化。
(2)注意IndexWriter,IndexReader等均需要耗费较大的资源用于创建实例,因此如非必要,使用单例模式创建一个实例后。
3、索引、Document、Filed之间的关系
简而言之,多个Filed组成一个Document,多个Document组成一个索引。
它们之间通过以下方法相互调用:
Document doc = new Document();
Field pathField = new StringField("path", filetoIndex.getPath(),Field.Store.YES);
doc.add(pathField); writer.addDocument(doc);
二、关于Field
(一)创建一个域(field)的基本方法
Field field = new Field("filename", f.getName(), Field.Store.YES, Field.Index.NOT_ANALYZED);
Field field = new Field("contents", new FileReader(f));
Field field = new Field("fullpath", f.getCanonicalPath(), Field.Store.YES, Field.Index.NOT_ANALYZED)
Filed的四个参数分别代表:
<pre name="code" class="java">Field field = new StringField("path", filetoIndex.getPath(),Field.Store.YES);
Field field = new LongField("modified", filetoIndex.lastModified(),Field.Store.NO);
Field field = new TextField("contents", new FileReader(filetoIndex));
在4.x以后,StringField即为NOT_ANALYZED的(即不对域的内容进行分割分析),而textField是ANALYZED的,因此,创建Field对象时,无需再指定此属性。见http://stackoverflow.com/questions/19042587/how-to-prevent-a-field-from-not-analyzing-in-lucene
for sorting or access through the field cache
Field field = new TextField("contents", new FileReader(filetoIndex));
只对纯文本有效。对于word,excel,pdf等富文本,FileReader读取到的内容只是一些乱码,并不能形成有效的索引。
http://stackoverflow.com/questions/16640292/lucene-4-2-0-index-pdf
and for your purposes, it will only handle plain text. This works on the Unix philosophy. Lucene indexes content. Tika extracts content from rich documents. I've added links to a couple of examples using Tika, one with Lucene directly, the other using Solr
(which you might want to consider as well).
doc.add(new TextField("contents", TikaBasicUtil.extractContent(filetoIndex),Field.Store.NO));
注意此处不能使用StringField,因为StringField限制了字符串的大小不能超过32766,否则会报异常IllegalArgumentException:Document contains at least one immense term in field="contents" (whose UTF8 encoding is longer than the max length 32766)*/
使用Tika索引富文本的简单示例如下:
package org.jediael.util; import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream; import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.parser.AutoDetectParser;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.Parser;
import org.apache.tika.sax.BodyContentHandler;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException; public class TikaBasicUtil { public static String extractContent(File f) {
//1、创建一个parser
Parser parser = new AutoDetectParser();
InputStream is = null;
try {
Metadata metadata = new Metadata();
metadata.set(Metadata.RESOURCE_NAME_KEY, f.getName());
is = new FileInputStream(f);
ContentHandler handler = new BodyContentHandler();
ParseContext context = new ParseContext();
context.set(Parser.class,parser); //2、执行parser的parse()方法。
parser.parse(is,handler, metadata,context); String returnString = handler.toString(); System.out.println(returnString.length());
return returnString;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (TikaException e) {
e.printStackTrace();
}finally {
try {
if(is!=null) is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return "No Contents";
}
}
Directory returnIndexDir = FSDirectory.open(indexDir);
IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_48,new StandardAnalyzer(Version.LUCENE_48));
iwc.setOpenMode(IndexWriterConfig.OpenMode.CREATE);
writer = new IndexWriter(returnIndexDir, iwc);
System.out.println(writer.getConfig().getOpenMode()+"");
System.out.println(iwc.getOpenMode());
创建一个IndexWriter时,需要2个参数,一个是Directory对象,用于指定所创建的索引写到哪个地方;另一个是IndexWriterConfig对象,用于指定writer的配置。
- java.lang.Object
- org.apache.lucene.index.LiveIndexWriterConfig
- org.apache.lucene.index.IndexWriterConfig
- All Implemented Interfaces:
- Cloneable
- (2)Holds all the configuration that is used to create an
IndexWriter.
OnceIndexWriterhas
been created with this object, changes to this object will not affect theIndexWriterinstance. - (3)IndexWriterConfig.OpenMode:指明了打开索引目录的方式,有以下三种:
- APPEND:Opens an existing index. 若原来存在索引,则将本次索引的内容追加进来。不管文档是否与原来是否重复,因此若2次索引的文档相同,则返回结果数则为原来的2倍。
- CREATE:Creates a new index or overwrites an existing one. 若原来存在索引,则先将其删除,再创建新的索引
- CREATE_OR_APPEND【默认值】:Creates a new index if one does not exist, otherwise it opens the index and documents will be appended.
writer.addDocument(doc);
writer.forceMerge(2);
索引的优化是将索引结果文件归为一个或者有限的多个,它加大的索引过程中的消耗,减少了搜索时的消耗。
IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_48,new StandardAnalyzer(Version.LUCENE_48));
writer = new IndexWriter(IndexDir, iwc);
writer.addDocument(doc, new SimpleAnalyzer(Version.LUCENE_48));
版权声明:本文为博主原创文章,未经博主允许不得转载。
【Lucene4.8教程之二】索引 2014-06-16 11:30 3845人阅读 评论(0) 收藏的更多相关文章
- 【solr专题之二】配置文件:solr.xml solrConfig.xml schema.xml 分类: H4_SOLR/LUCENCE 2014-07-23 21:30 1959人阅读 评论(0) 收藏
1.关于默认搜索域 If you are using the Lucene query parser, queries that don't specify a field name will use ...
- Lucene学习总结之三:Lucene的索引文件格式(1) 2014-06-25 14:15 1124人阅读 评论(0) 收藏
Lucene的索引里面存了些什么,如何存放的,也即Lucene的索引文件格式,是读懂Lucene源代码的一把钥匙. 当我们真正进入到Lucene源代码之中的时候,我们会发现: Lucene的索引过程, ...
- spark1.3.1使用基础教程 分类: B8_SPARK 2015-04-28 11:10 1651人阅读 评论(0) 收藏
spark可以通过交互式命令行及编程两种方式来进行调用: 前者支持scala与python 后者支持scala.python与java 本文参考https://spark.apache.org/d ...
- Gora官方文档之二:Gora对Map-Reduce的支持 分类: C_OHTERS 2015-01-31 11:27 232人阅读 评论(0) 收藏
参考官方文档:http://gora.apache.org/current/tutorial.html 项目代码见:https://code.csdn.net/jediael_lu/mygoradem ...
- JSON入门之二:org.json的基本用法 分类: C_OHTERS 2014-05-14 11:25 6001人阅读 评论(0) 收藏
java中用于解释json的主流工具有org.json.json-lib与gson,本文介绍org.json的应用. 官方文档: http://www.json.org/java/ http://de ...
- 【Lucene4.8教程之三】搜索 2014-06-21 09:53 1532人阅读 评论(0) 收藏
1.关键类 Lucene的搜索过程中涉及的主要类有以下几个: (1)IndexSearcher:执行search()方法的类 (2)IndexReader:对索引文件进行读操作,并为IndexSear ...
- Mahout快速入门教程 分类: B10_计算机基础 2015-03-07 16:20 508人阅读 评论(0) 收藏
Mahout 是一个很强大的数据挖掘工具,是一个分布式机器学习算法的集合,包括:被称为Taste的分布式协同过滤的实现.分类.聚类等.Mahout最大的优点就是基于hadoop实现,把很多以前运行于单 ...
- 【solr基础教程之二】索引 分类: H4_SOLR/LUCENCE 2014-07-18 21:06 3331人阅读 评论(0) 收藏
一.向Solr提交索引的方式 1.使用post.jar进行索引 (1)创建文档xml文件 <add> <doc> <field name="id"&g ...
- 【Lucene4.8教程之五】Luke 2014-06-24 15:12 1092人阅读 评论(0) 收藏
一.Luke基本内容 1.Luke简介 Luke可用于查看Lucene创建的索引,并对其进行基本操作. 2.创建Luke (1)从Github上下载源文件 https://github.com/tar ...
随机推荐
- 【开卷故意】JAVA正則表達式模版
专业既然是机器学习.那工作肯定也是继续和数据打交道,那么问题来了,非常多时候推荐算法和数据挖掘算法都是现成可用的,平台初建,重点还在数据过滤和抽取.如何高效的抽取数据? 利用往常算法比赛中经常使用的字 ...
- Linux 获取上个月的第一秒和上个月的最后一秒
因为写脚本需求须要获得上个月的第一秒和上个月的最后一秒,查阅了相关资料,并通过自己实践.找到了以下这样的方法能满足要求.在此备注,若有其它好的方法.请留言.本人将不胜感激. 获取上个月的第一秒: da ...
- hdoj 2122 Ice_cream’s world III【最小生成树】
Ice_cream's world III Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Ot ...
- 开源课程管理系统(CMS):Moodle
开源课程管理系统(CMS):Moodle 一.总结 1.php开发的cms,可借鉴参考用 二.Moodle(百度) Moodle(Modular Object-Oriented Dynamic Lea ...
- 1.11 Python基础知识 - 序列:元组
元组(tuple)是一组有序系列,元组和列表是否相似,但是元组是不可变的对象,不能修改.添加或删除元组中的元素,但可以访问元组中的元素 元组的定义: 元组采用圆括号中用逗号分隔的元素 元组的基本操作和 ...
- Android网络框架OkHttp之get请求(源码初识)
概括 OkHttp现在很火呀.于是上个星期就一直在学习OkHttp框架,虽然说起来已经有点晚上手了,貌似是2013年就推出了.但是现在它版本更加稳定了呀.这不,说着说着,OkHttp3.3版本在这几天 ...
- Flask项目之手机端租房网站的实战开发(四)
说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家! 接着上一篇博客继续往下写 :https://blog.csdn.net/qq_41782425/article/details/8 ...
- Java网络编程之TCP、UDP
Java网络编程之TCP.UDP 2014-11-25 15:23 513人阅读 评论(0) 收藏 举报 分类: java基础及多线程(28) 版权声明:本文为博主原创文章,未经博主允许不得转载. ...
- Invalid property 'annotatedClasses' of bean class
Invalid property 'annotatedClasses' of bean class 在整合Hibernate和Spring时出现,Invalid property 'annotated ...
- keytool用法总结
一.keytool的概念 keytool 是个密钥和证书管理工具.它使用户能够管理自己的公钥/私钥对及相关证书,用于(通过数字签名)自我认证(用户向别的用户/服务认证自己)或数据完整性以及认证服务.在 ...