- 浏览: 336731 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
327764984:
CommonSql里不知道把PreparedStatment和 ...
Connection.setAutoCommit使用的注意事项 -
netwelfare:
文章讲解的不详细啊,很多东西没有讲解出来。看到这篇文章讲解的挺 ...
java字符串的拆分 lang.String.split -
iceage1980:
博主你好 我用了你这个代码 为什么总是在 if (this. ...
MD5 码 校 验 -
wisdomtl:
最后一段代码有写小的错误最后一个具体工厂的实现应该返回Cowb ...
JAVA设计模式之工厂模式 -
jateide:
网上随便转载的东西,自己都没有经过使用,好意思发出来,而且还不 ...
正则表达式中后向引用、零宽断言、负向零宽断言的解释用法
官网: http://lucene.apache.org/
lucene中国: lucene.com.cn
1. 简介
Lucene 是apache 软件基金会4 jakarta 项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,
提供了 完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。Lucene 的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现
全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。
2. 下载
http://labs.renren.com/apache-mirror//lucene/java/3.0.3/
3. 测试
在eclipse 中邪见项目 Lucence3.0Test, 将一下包导入到build 路径中
lucene-core-3.0.2.jar
lucene-demos-3.0.2.jar
lucene-analyzers-3.0.2.jar
lucene-fast-vector-highlighter-3.0.2.jar
lucene-highlighter-3.0.2.jar
lucene-memory-3.0.2.jar
在任意目录下新建两个文件夹:
用来存放lucence 进行分词的文件和生成的index 。如下图:file1 用来存放进行分词的文件,里面存放有N 个txt 文件,txt 文件的内容任意,如:我们都是中国人,index 文件夹是新建的,里面不要有任何的文件,是用来存储生成的index 的
4. 代码
新建创建索引的类,以及测试
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.document.DateTools;
import
org.apache.lucene.document.Document;
import
org.apache.lucene.document.Field;
import
org.apache.lucene.index.IndexWriter;
import
org.apache.lucene.store.FSDirectory;
import
org.wltea.analyzer.lucene.IKAnalyzer;
public
class
IndexerOK {
private
static
String INDEX_DIR =
"D:\\nutchwork\\LucenceTestDir\\index";
//
索引存放目录
private
static
String DATA_DIR =
"D:\\nutchwork\\LucenceTestDir\\file1";
//
小文件存放的目录
public
static
void
main(String[] args)
throws
Exception {
long
start
=
new
Date().getTime();
int
numIndexed = index(
new
File(INDEX_DIR),
new
File(DATA_DIR));
//
调用index
方法
long
end =
new
Date().getTime();
System.out.println("Indexing
" + numIndexed + " files took "
+ (end - start) + "
milliseconds");
}
/**
*
索引dataDir
下的.txt
文件,并储存在indexDir
下,返回索引的文件数量
*
*
@param
indexDir
*
@param
dataDir
*
@return
int
*
@throws
IOException
*/
public
static
int
index(File indexDir, File dataDir)
throws
IOException {
if
(!dataDir.exists() || !dataDir.isDirectory()) {
throw
new
IOException(dataDir
+ " does not exist or is not a
directory");
}
Analyzer analyzer =
new
IKAnalyzer();
//
采用的分词器
//
第三个参数 为true
表示新建,false
表示添加到原有索引中
IndexWriter writer =
new
IndexWriter(FSDirectory.open(indexDir),
analyzer,
true
,
IndexWriter.MaxFieldLength.LIMITED);
indexDirectory(writer, dataDir);
//
调用indexDirectory
方法
int
numIndexed = writer.numDocs();
writer.optimize();
writer.close();
return
numIndexed;
}
/**
*
循环遍历目录下的所有.txt
文件并进行索引
*
*
@param
writer
*
@param
dir
*
@throws
IOException
*/
private
static
void
indexDirectory(IndexWriter writer, File dir)
throws
IOException {
File[] files = dir.listFiles();
for
(
int
i = 0; i < files.length; i++) {
File f = files[i];
if
(f.isDirectory()) {
indexDirectory(writer, f);
// recurse
}
else
if
(f.getName().endsWith(".txt")) {
indexFile(writer, f);
}
}
}
/**
*
对单个txt
文件进行索引
*
*
@param
writer
*
@param
f
*
@throws
IOException
*/
private
static
void
indexFile(IndexWriter writer, File f)
throws
IOException {
if
(f.isHidden() || !f.exists() || !f.canRead()) {
return
;
}
System.out.println("Indexing
" + f.getCanonicalPath());
Document doc =
new
Document();
// doc.add(new Field("contents", new
FileReader(f)));
doc.add(
new
Field("filename",
f.getCanonicalPath(), Field.Store.YES, Field.Index.ANALYZED));
String temp =
FileReaderAll(f.getCanonicalPath(), "GBK");
System.out.println(temp);
doc.add(
new
Field("TTT", temp, Field.Store.YES, Field.Index.ANALYZED));
doc.add(
new
Field("path", f.getPath(), Field.Store.YES,
Field.Index.ANALYZED));
doc.add(
new
Field("modified", DateTools.timeToString(f.lastModified(),
DateTools.Resolution.MINUTE),
Field.Store.YES,
Field.Index.ANALYZED));
FileInputStream fis =
new
FileInputStream(f);
//
按照
UTF-8
编码方式将字节流转化为字符流
InputStreamReader isr =
new
InputStreamReader(fis, "utf-8");
//
从字符流中获取文本并进行缓冲
BufferedReader br =
new
BufferedReader(isr);
doc.add(
new
Field("contents", br));
writer.setUseCompoundFile(
false
);
writer.addDocument(doc);
}
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;
}
}
运行结果:
Indexing
D:\nutchwork\LucenceTestDir\file1\1.txt
我们是中国人
Indexing D:\nutchwork\LucenceTestDir\file1\2.txt
我们是中国人
Indexing D:\nutchwork\LucenceTestDir\file1\3.txt
我们是中国人
Indexing D:\nutchwork\LucenceTestDir\file1\4.txt
我们是中国人
Indexing 4 files took 2293 milliseconds
新建查询的类以及测试:
import
java.io.File;
import
java.io.StringReader;
import
java.util.Date;
import
java.util.List;
import
org.apache.lucene.analysis.Analyzer;
import
org.apache.lucene.analysis.TokenStream;
import
org.apache.lucene.document.Document;
import
org.apache.lucene.document.Fieldable;
import
org.apache.lucene.search.IndexSearcher;
import
org.apache.lucene.search.Query;
import
org.apache.lucene.search.ScoreDoc;
import
org.apache.lucene.search.Sort;
import
org.apache.lucene.search.SortField;
import
org.apache.lucene.search.TopDocs;
import
org.apache.lucene.search.highlight.Highlighter;
import
org.apache.lucene.search.highlight.QueryScorer;
import
org.apache.lucene.search.highlight.SimpleFragmenter;
import
org.apache.lucene.search.highlight.SimpleHTMLFormatter;
import
org.apache.lucene.store.FSDirectory;
import
org.wltea.analyzer.lucene.IKAnalyzer;
import
org.wltea.analyzer.lucene.IKQueryParser;
import
org.wltea.analyzer.lucene.IKSimilarity;
public
class
SearchQueryOK {
private
static
String INDEX_DIR =
"D:\\nutchwork\\LucenceTestDir\\index";
//
索引所在的路径
private
static
String KEYWORD = "
中国人";
//
关键词
private
static
int
TOP_NUM = 100;
//
显示前100
条结果
public
static
void
main(String[] args)
throws
Exception {
File indexDir =
new
File(INDEX_DIR);
if
(!indexDir.exists() || !indexDir.isDirectory()) {
throw
new
Exception(indexDir
+ " does not exist or is not a
directory.");
}
search(indexDir, KEYWORD);
//
调用search
方法进行查询
}
/**
*
查询
*
*
@param
indexDir
*
@param
q
*
@throws
Exception
*/
public
static
void
search(File indexDir, String q)
throws
Exception {
IndexSearcher is =
new
IndexSearcher(FSDirectory.open(indexDir),
true
);
// read-only
String[] field =
{"TTT","modified","filename"};
long
start
=
new
Date().getTime();
// start time
//
高亮设置
Analyzer analyzer =
new
IKAnalyzer();
//
设定分词器
Query query2 = IKQueryParser.parseMultiField(field,
KEYWORD);
//
实例化搜索器
IndexSearcher isearcher1 =
new
IndexSearcher(FSDirectory.open(indexDir));
//
在索引器中使用IKSimilarity
相似度评估器
isearcher1.setSimilarity(
new
IKSimilarity());
Sort sort =
new
Sort(
new
SortField("path", SortField.DOC,
false
));
//TermQuery q1 = new TermQuery(new
Term("filename", "1"));
//
搜索相似度最高的记录
TopDocs topDocs1 = isearcher1.search(query2,
null
, TOP_NUM,sort);
ScoreDoc[] hits3 = topDocs1.scoreDocs;
SimpleHTMLFormatter simpleHtmlFormatter
=
new
SimpleHTMLFormatter(
"<span
style='color:#ff0000'>", "</span>");
//
设定高亮显示的格式,也就是对高亮显示的词组加上前缀后缀
Highlighter highlighter =
new
Highlighter(simpleHtmlFormatter,
new
QueryScorer(query2));
for
(
int
i = 0; i < hits3.length; i++) {
Document doc = is.doc(hits3[i].doc);
String docTTT =
doc.get("TTT");
highlighter.setTextFragmenter(
new
SimpleFragmenter(docTTT.length()));
//
设置每次返回的字符数.
想必大家在使用搜索引擎的时候也没有一并把全部数据展示出来吧,当然这里也是设定只展示部分数据
TokenStream tokenStream = analyzer.tokenStream("",
new
StringReader(docTTT));
String str =
highlighter.getBestFragment(tokenStream, docTTT);
System.out.println("
高亮设置: " + str );
String docModified =
doc.get("filename");
highlighter.setTextFragmenter(
new
SimpleFragmenter(docModified.length()));
TokenStream tokenStream2 =
analyzer.tokenStream("",
new
StringReader(docModified));
String str2 =
highlighter.getBestFragment(tokenStream2, docModified);
System.out.println("
高亮设置: " + str2 );
List<Fieldable> list =
doc.getFields();
for
(
int
j = 0; j < list.size(); j++) {
Fieldable fieldable = list.get(j);
System.out.println(fieldable.name()
+ " : "
+ fieldable.stringValue() +
"<br>");
}
}
long
end =
new
Date().getTime();
// end time
System.out.println("Found "
+ hits3.length
+ " document(s) (in " +
(end - start)
+ " milliseconds) that matched
query '" + q + "':");
}
}
对索引的操作类:
import
java.io.File;
import
java.io.IOException;
import
java.sql.Connection;
import
java.sql.SQLException;
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.IndexReader;
import
org.apache.lucene.index.IndexWriter;
import
org.apache.lucene.index.Term;
import
org.apache.lucene.store.Directory;
import
org.apache.lucene.store.FSDirectory;
import
org.apache.lucene.util.Version;
import
org.wltea.analyzer.lucene.IKAnalyzer;
public
class
ManageIndexFile {
private
static
String INDEX_DIR =
"D:\\nutchwork\\LucenceTestDir\\index";
//
索引存放目录
//
删除索引
public
static
void
DeleteIndex(SearchDocBean bean)
throws
IOException {
Directory dir = FSDirectory.open(
new
File(INDEX_DIR));
IndexReader reader =
IndexReader.open(dir,
false
);
Term term =
new
Term("modified", bean.getId());
int
count
= reader.deleteDocuments(term);
reader.close();
System.out.println("Successful
Delete " + count + " path==" + bean.getId());
}
public
static
void
DeleteIndex(
int
[]
posIDS)
throws
IOException {
Directory dir = FSDirectory.open(
new
File(INDEX_DIR));
IndexReader reader =
IndexReader.open(dir,
false
);
for
(
int
i = 0; i < posIDS.length; i++) {
Term term =
new
Term("posID", Integer.toString(posIDS[i]));
reader.deleteDocuments(term);
}
reader.close();
}
//
更新索引
public
static
void
UpdateIndex(SearchDocBean bean)
throws
IOException {
Directory dir = FSDirectory.open(
new
File(INDEX_DIR));
IndexReader reader =
IndexReader.open(dir,
false
);
Term term =
new
Term("modified", bean.getId());
reader.deleteDocuments(term);
reader.close();
IndexWriter writer =
new
IndexWriter(FSDirectory.open(
new
File(
INDEX_DIR)),
new
StandardAnalyzer(Version.LUCENE_CURRENT),
true
,
IndexWriter.MaxFieldLength.LIMITED);
Document doc =
new
Document();
doc.add(
new
Field("modified", bean.getId(), Field.Store.YES,
Field.Index.NOT_ANALYZED));
writer.addDocument(doc);
writer.optimize();
writer.close();
}
//
增加索引
public
static
void
AddIndex(SearchDocBean bean,
Connection conn)
throws
IOException, SQLException {
Analyzer analyzer =
new
IKAnalyzer();
//
采用的分词器
IndexWriter writer =
new
IndexWriter(FSDirectory.open(
new
File(
INDEX_DIR)), analyzer,
false
,
IndexWriter.MaxFieldLength.LIMITED);
Document doc =
new
Document();
doc.add(
new
Field("filename", bean.getFileName(), Field.Store.YES,
Field.Index.ANALYZED));
doc.add(
new
Field("path", bean.getPath(), Field.Store.YES,
Field.Index.ANALYZED));
doc.add(
new
Field("dateTime", bean.getId(), Field.Store.YES,
Field.Index.ANALYZED));
doc.add(
new
Field("TTT", bean.getContents(), Field.Store.YES,
Field.Index.ANALYZED));
writer.setUseCompoundFile(
false
);
writer.addDocument(doc);
writer.optimize();
writer.close();
}
}
封装起来的查询结果:
public
class
SearchDocBean {
private
String id;
private
String path;
private
String contents;
private
String dateTime;
public
String getId() {
return
id;
}
public
void
setId(String id) {
this
.id =
id;
}
public
String getPath() {
return
path;
}
public
void
setPath(String path) {
this
.path
= path;
}
public
String getContents() {
return
contents;
}
public
void
setContents(String contents) {
this
.contents
= contents;
}
public
String getDateTime() {
return
dateTime;
}
public
void
setDateTime(String dateTime) {
this
.dateTime
= dateTime;
}
public
String getFileName() {
return
fileName;
}
public
void
setFileName(String fileName) {
this
.fileName
= fileName;
}
private
String fileName;
}
下面是serach 中国人的 结果:
高亮设置: <span style='color:#ff0000'>
中国人</span>
高亮设置: null
filename : D:\nutchwork\LucenceTestDir\file1\1.txt<br>
TTT :
我们是中国人<br>
path : D:\nutchwork\LucenceTestDir\file1\1.txt<br>
modified : 201107161115<br>
高亮设置: <span
style='color:#ff0000'>
中国人</span>
高亮设置: null
filename : D:\nutchwork\LucenceTestDir\file1\2.txt<br>
TTT :
我们是中国人<br>
path : D:\nutchwork\LucenceTestDir\file1\2.txt<br>
modified : 201107161115<br>
高亮设置: <span
style='color:#ff0000'>
中国人</span>
高亮设置: null
filename : D:\nutchwork\LucenceTestDir\file1\3.txt<br>
TTT :
我们是中国人<br>
path : D:\nutchwork\LucenceTestDir\file1\3.txt<br>
modified : 201107161115<br>
高亮设置: <span
style='color:#ff0000'>
中国人</span>
高亮设置: null
filename : D:\nutchwork\LucenceTestDir\file1\4.txt<br>
TTT :
我们是中国人<br>
path : D:\nutchwork\LucenceTestDir\file1\4.txt<br>
modified : 201107161115<br>
Found 4 document(s) (in 717 milliseconds) that matched query '
中国人':
整个工程:基本上是从网上找到的代码,运行了下,算是有一个大概的了解。
Lucene 简介
Lucene 是一个基于 Java 的全文信息检索工具包,它不是一个完整的搜索应用程序,而是为你的应用程序提供索引和搜索功能。Lucene 目前是 Apache Jakarta 家族中的一个开源项目。也是目前最为流行的基于 Java 开源全文检索工具包。
目前已经有很多应用程序的搜索功能是基于 Lucene 的,比如 Eclipse 的帮助系统的搜索功能。Lucene 能够为文本类型的数据建立索引,所以你只要能把你要索引的数据格式转化的文本的,Lucene 就能对你的文档进行索引和搜索。比如你要对一些 HTML 文档,PDF 文档进行索引的话你就首先需要把 HTML 文档和 PDF 文档转化成文本格式的,然后将转化后的内容交给 Lucene 进行索引,然后把创建好的索引文件保存到磁盘或者内存中,最后根据用户输入的查询条件在索引文件上进行查询。不指定要索引的文档的格式也使 Lucene 能够几乎适用于所有的搜索应用程序。
图 1 表示了搜索应用程序和 Lucene 之间的关系,也反映了利用 Lucene 构建搜索应用程序的流程:
索引是现代搜索引擎的核心,建立索引的过程就是把源数据处理成非常方便查询的索引文件的过程。为什么索引这么重要呢,试想你现在要在大量的文 档中搜索含有某个关键词的文档,那么如果不建立索引的话你就需要把这些文档顺序的读入内存,然后检查这个文章中是不是含有要查找的关键词,这样的话就会耗 费非常多的时间,想想搜索引擎可是在毫秒级的时间内查找出要搜索的结果的。这就是由于建立了索引的原因,你可以把索引想象成这样一种数据结构,他能够使你 快速的随机访问存储在索引中的关键词,进而找到该关键词所关联的文档。Lucene 采用的是一种称为反向索引(inverted index )的机制。反向索引就是说我们维护了一个词 / 短语表,对于这个表中的每个词 / 短语,都有一个链表描述了有哪些文档包含了这个词 / 短语。这样在用户输入查询条件的时候,就能非常快的得到搜索结果。我们将在本系列文章的第二部分详细介绍 Lucene 的索引机制,由于 Lucene 提供了简单易用的 API ,所以即使读者刚开始对全文本进行索引的机制并不太了解,也可以非常容易的使用 Lucene 对你的文档实现索引。
对文档建立好索引后,就可以在这些索引上面进行搜索了。搜索引擎首先会对搜索的关键词进行解析,然后再在建立好的索引上面进行查找,最终返回和用户输入的关键词相关联的文档。
Lucene 软件包分析
Lucene 软件包的发布形式是一个 JAR 文件,下面我们分析一下这个 JAR 文件里面的主要的 JAVA 包,使读者对之有个初步的了解。
Package: org.apache.lucene.document
这个包提供了一些为封装要索引的文档所需要的类,比如 Document, Field 。这样,每一个文档最终被封装成了一个 Document 对象。
Package: org.apache.lucene.analysis
这个包主要功能是对文档进行分词,因为文档在建立索引之前必须要进行分词,所以这个包的作用可以看成是为建立索引做准备工作。
Package: org.apache.lucene.index
这个包提供了一些类来协助创建索引以及对创建好的索引进行更新。这里面有两个基础的类:IndexWriter 和 IndexReader ,其中 IndexWriter 是用来创建索引并添加文档到索引中的,IndexReader 是用来删除索引中的文档的。
Package: org.apache.lucene.search
这个包提供了对在建立好的索引上进行搜索所需要的类。比如 IndexSearcher 和 Hits, IndexSearcher 定义了在指定的索引上进行搜索的方法,Hits 用来保存搜索得到的结果。
假设我们的电脑的目录中含有很多文本文档,我们需要查找哪些文档含有某个关键词。为了实现这种功能,我们首先利用 Lucene 对这个目录中的文档建立索引,然后在建立好的索引中搜索我们所要查找的文档。通过这个例子读者会对如何利用 Lucene 构建自己的搜索应用程序有个比较清楚的认识。
为了对文档进行索引,Lucene 提供了五个基础的类,他们分别是 Document, Field, IndexWriter, Analyzer, Directory 。下面我们分别介绍一下这五个类的用途:
Document
Document 是用来描述文档的,这里的文档可以指一个 HTML 页面,一封电子邮件,或者是一个文本文件。一个 Document 对象由多个 Field 对象组成的。可以把一个 Document 对象想象成数据库中的一个记录,而每个 Field 对象就是记录的一个字段。
Field
Field 对象是用来描述一个文档的某个属性的,比如一封电子邮件的标题和内容可以用两个 Field 对象分别描述。
Analyzer
在一个文档被索引之前,首先需要对文档内容进行分词处理,这部分工作就是由 Analyzer 来做的。Analyzer 类是一个抽象类,它有多个实现。针对不同的语言和应用需要选择适合的 Analyzer 。Analyzer 把分词后的内容交给 IndexWriter 来建立索引。
IndexWriter
IndexWriter 是 Lucene 用来创建索引的一个核心的类,他的作用是把一个个的 Document 对象加到索引中来。
Directory
这个类代表了 Lucene 的索引的存储的位置,这是一个抽象类,它目前有两个实现,第一个是 FSDirectory ,它表示一个存储在文件系统中的索引的位置。第二个是 RAMDirectory ,它表示一个存储在内存当中的索引的位置。
熟悉了建立索引所需要的这些类后,我们就开始对某个目录下面的文本文件建立索引了,清单 1 给出了对某个目录下的文本文件建立索引的源代码。
package TestLucene; import java.io.File; import java.io.FileReader; import java.io.Reader; 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; /** * This class demonstrate the process of creating index with Lucene * for text files */ public class TxtFileIndexer { public static void main(String[] args) throws Exception{ //indexDir is the directory that hosts Lucene's index files File indexDir = new File("D:\\luceneIndex"); //dataDir is the directory that hosts the text files that to be indexed File dataDir = new File("D:\\luceneData"); Analyzer luceneAnalyzer = new StandardAnalyzer(); File[] dataFiles = dataDir.listFiles(); IndexWriter indexWriter = new IndexWriter(indexDir,luceneAnalyzer,true); long startTime = new Date().getTime(); for(int i = 0; i < dataFiles.length; i++){ if(dataFiles[i].isFile() && dataFiles[i].getName().endsWith(".txt")){ System.out.println("Indexing file " + dataFiles[i].getCanonicalPath()); Document document = new Document(); Reader txtReader = new FileReader(dataFiles[i]); document.add(Field.Text("path",dataFiles[i].getCanonicalPath())); document.add(Field.Text("contents",txtReader)); indexWriter.addDocument(document); } } indexWriter.optimize(); indexWriter.close(); long endTime = new Date().getTime();
System.out.println("It takes " + (endTime - startTime) + " milliseconds to create index for the files in directory " + dataDir.getPath()); } } |
在清单 1 中,我们注意到类 IndexWriter 的构造函数需要三个参数,第一个参数指定了所创建的索引要存放的位置,他可以是一个 File 对象,也可以是一个 FSDirectory 对象或者 RAMDirectory 对象。第二个参数指定了 Analyzer 类的一个实现,也就是指定这个索引是用哪个分词器对文挡内容进行分词。第三个参数是一个布尔型的变量,如果为 true 的话就代表创建一个新的索引,为 false 的话就代表在原来索引的基础上进行操作。接着程序遍历了目录下面的所有文本文档,并为每一个文本文档创建了一个 Document 对象。然后把文本文档的两个属性:路径和内容加入到了两个 Field 对象中,接着在把这两个 Field 对象加入到 Document 对象中,最后把这个文档用 IndexWriter 类的 add 方法加入到索引中去。这样我们便完成了索引的创建。接下来我们进入在建立好的索引上进行搜索的部分。
利用 Lucene 进行搜索就像建立索引一样也是非常方便的。在上面一部分中,我们已经为一个目录下的文本文档建立好了索引,现在我们就要在这个索引上进行搜索以找到包含某 个关键词或短语的文档。Lucene 提供了几个基础的类来完成这个过程,它们分别是呢 IndexSearcher, Term, Query, TermQuery, Hits. 下面我们分别介绍这几个类的功能。
Query
这是一个抽象类,他有多个实现,比如 TermQuery, BooleanQuery, PrefixQuery. 这个类的目的是把用户输入的查询字符串封装成 Lucene 能够识别的 Query 。
Term
Term 是搜索的基本单位,一个 Term 对象有两个 String 类型的域组成。生成一个 Term 对象可以有如下一条语句来完成:Term term = new Term(“fieldName”,”queryWord”); 其中第一个参数代表了要在文档的哪一个 Field 上进行查找,第二个参数代表了要查询的关键词。
TermQuery
TermQuery 是抽象类 Query 的一个子类,它同时也是 Lucene 支持的最为基本的一个查询类。生成一个 TermQuery 对象由如下语句完成: TermQuery termQuery = new TermQuery(new Term(“fieldName”,”queryWord”)); 它的构造函数只接受一个参数,那就是一个 Term 对象。
IndexSearcher
IndexSearcher 是用来在建立好的索引上进行搜索的。它只能以只读的方式打开一个索引,所以可以有多个 IndexSearcher 的实例在一个索引上进行操作。
Hits
Hits 是用来保存搜索的结果的。
介绍完这些搜索所必须的类之后,我们就开始在之前所建立的索引上进行搜索了,清单 2 给出了完成搜索功能所需要的代码。
package TestLucene; import java.io.File; import org.apache.lucene.document.Document; import org.apache.lucene.index.Term; import org.apache.lucene.search.Hits; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.TermQuery; import org.apache.lucene.store.FSDirectory; /** * This class is used to demonstrate the * process of searching on an existing * Lucene index * */ public class TxtFileSearcher { public static void main(String[] args) throws Exception{ String queryStr = "lucene"; //This is the directory that hosts the Lucene index File indexDir = new File("D:\\luceneIndex"); FSDirectory directory = FSDirectory.getDirectory(indexDir,false); IndexSearcher searcher = new IndexSearcher(directory); if(!indexDir.exists()){ System.out.println("The Lucene index is not exist"); return; } Term term = new Term("contents",queryStr.toLowerCase()); TermQuery luceneQuery = new TermQuery(term); Hits hits = searcher.search(luceneQuery); for(int i = 0; i < hits.length(); i++){ Document document = hits.doc(i); System.out.println("File: " + document.get("path")); } } } |
在清单 2 中,类 IndexSearcher 的构造函数接受一个类型为 Directory 的对象,Directory 是一个抽象类,它目前有两个子类:FSDirctory 和 RAMDirectory. 我们的程序中传入了一个 FSDirctory 对象作为其参数,代表了一个存储在磁盘上的索引的位置。构造函数执行完成后,代表了这个 IndexSearcher 以只读的方式打开了一个索引。然后我们程序构造了一个 Term 对象,通过这个 Term 对象,我们指定了要在文档的内容中搜索包含关键词”lucene” 的文档。接着利用这个 Term 对象构造出 TermQuery 对象并把这个 TermQuery 对象传入到 IndexSearcher 的 search 方法中进行查询,返回的结果保存在 Hits 对象中。最后我们用了一个循环语句把搜索到的文档的路径都打印了出来。 好了,我们的搜索应用程序已经开发完毕,怎么样,利用 Lucene 开发搜索应用程序是不是很简单。
本文首先介绍了 Lucene 的一些基本概念,然后开发了一个应用程序演示了利用 Lucene 建立索引并在该索引上进行搜索的过程。希望本文能够为学习 Lucene 的读者提供帮助。
- lucene.zip (89.3 KB)
- 下载次数: 12
发表评论
-
向数据库插入中文乱码【转】
2015-05-02 19:35 1436又遇到乱码问题,这个编码问题有时候真是让人头大。找了半 ... -
查询最近1天,2天,3天,一个星期,两个星期的记录
2013-08-05 19:28 1267if you use SQL Server, ... -
使用PLSQL_developer创建用户【转】
2013-01-04 10:33 4388Oracle如何实现创建数据库、备份数据库及 ... -
Oracle回滚注意事项
2012-04-11 17:27 1153回滚到fisrt()时注意使用next()时需要将光标移到第一 ... -
用java调用oracle存储过程总结
2012-02-17 14:30 01、什么是存储过程。存储过程是数据库服务器端的一段程序,它 ... -
Sphinx基于SQL的全文检索引擎简介
2012-02-17 10:28 5824Sphinx中文入门 ... -
SQL基本语句
2012-01-10 12:38 2179可以把 SQL 分为两个部分:数据操作语言 (DML) 和 ...
相关推荐
lucence学习笔记,中文的,适用于初学者学习,知识点案例较多。
《Lucence和Hadoop学习资料》是一份涵盖了两个重要大数据技术——Lucene和Hadoop的综合学习资源。Lucene是一个高性能、全文检索库,而Hadoop则是分布式计算框架的代表,两者在现代大数据处理和搜索领域中发挥着关键...
Lucence的描述以及重要的几个方法详解说明,Lucence的应用以及实例
lucence教程,通过这份文档可以学习lucence的相关知识
《Lucene学习手册》是一本深入浅出介绍Apache Lucene的宝贵资源,它为开发者提供了全面了解和掌握这个全文搜索引擎库的途径。Lucene是一个强大的、高性能的、开放源码的Java库,允许开发人员轻松地在应用程序中实现...
Lucence是一款开源的全文搜索引擎库,它为开发者提供了在Java应用程序中实现全文搜索功能的高级工具。这个"lucence jar.4.6.0版本所需jar包集合"是针对Lucence 4.6.0版本的一个完整依赖包集合,包含了运行和开发...
**正文** Lucene 是一个高性能、全文检索引擎库,由 Apache 软件基金会支持,广泛应用于各种信息检索系统。...这个“lucence 测试代码可运行”的项目是学习和理解 Lucene 工作原理的一个良好起点。
通过提供的“lucence”压缩包,你可以深入学习Lucene的开发文档,观看视频教程,并使用提供的开发jar包进行实践操作,逐步掌握这个强大的全文检索引擎。在实际项目中,结合具体的业务需求,灵活运用Lucene的各项功能...
通过以上步骤,你已经成功地迈出了Lucene学习的第一步。接下来,你可以深入探索Lucene的高级特性,如分片、多线程索引、近实时搜索、复杂查询表达式以及优化索引性能等。在实践中不断磨练,你将能够利用Lucene构建...
最新庖丁解牛分词法的使用demo,支持Lucene3.3、3.4等3.0以上版本,庖丁解牛的分词包为自己编译生成的,之前的2.0的版本不能支持Lucene3.0以上版本,所以需要从svn下载最新的庖丁解牛源码,生成jar文件(我同样已...
SpringBoot整合Lucene是一个常见的需求,特别是在构建高性能的全文搜索引擎时。Lucene是Apache软件基金会的一个开源项目,它提供了一个高性能、全文本搜索库。SpringBoot则是基于Spring框架的简化版,旨在简化Spring...
在这个名为 "lucence 完整项目" 的压缩包中,我们很显然会看到一个用于学习 Lucene 的实例项目,它涵盖了 Lucene 的基本概念、核心组件和实际应用。 **1. Lucene 基础** Lucene 的核心组成部分包括索引(Index)、...
《Lucene全方位实战指南》 Lucene,作为Apache软件基金会的一个开源项目,是Java语言实现的全文搜索引擎库。它提供了一个高效、可扩展的基础架构,用于在各种应用程序中实现全文检索功能。本教程将深入探讨Lucene的...
通过本文的学习,我们了解了如何使用 Lucene 实现文本高亮显示的方法。这一技术不仅可以提升用户的搜索体验,还能为开发者提供更丰富的文本处理手段。在实际应用中,还需要根据具体的业务需求和技术环境进行相应的...
这个资料集合包含了Lucene的相关课件和实际项目中的应用例子,对于学习和理解Lucene的内部机制以及如何在实际开发中运用它具有极高的价值。 1. **Lucene基础概念** - **全文检索**:Lucene的核心功能是全文检索,...
《一头扎进 Lucene 视频教程》是由 Java1234 出品的专业学习资源,专注于教授 Apache Lucene 这一强大的全文搜索引擎库。Lucene 是 Java 编写的开源库,广泛应用于信息检索和大数据分析领域。本教程旨在帮助初学者及...
### Lucene查询实现详解 #### 一、Lucene简介 Lucene是一款高性能、全功能的文本搜索引擎库。它提供了一套完整的搜索应用解决方案,包括全文检索、文档索引、相似度评分等功能。Lucene的核心是索引和搜索,开发者...