Lucene是apache组织的一个用java实现全文搜索引擎的开源项目。其功能非常的强大,但api其实很简单的,它最主要就是做两件事:建立索引和进行搜索。
1. 建立索引时最重要的几个术语

* Document:一个要进行索引的单元,相当于数据库的一行纪录,任何想要被索引的数据,都必须转化为Document对象存放。
* Field:Document中的一个字段,相当于数据库中的Column ,Field是lucene比较多概念一个术语,详细见后。
* IndexWriter:负责将Document写入索引文件。通常情况下,IndexWriter的构造函数包括了以下3个参数:索引存放的路径,分析 器和是否重新创建索引。特别注意的一点,当IndexWriter执行完addDocument方法后,一定要记得调用自身的close方法来关闭它。只 有在调用了close方法后,索引器才会将存放在内在中的所有内容写入磁盘并关闭输出流。
* Analyzer:分析器,主要用于文本分词。常用的有StandardAnalyzer分析器,StopAnalyzer分析器,WhitespaceAnalyzer分析器等。
* Directory:索引存放的位置。lucene提供了两种索引存放的位置,一种是磁盘,一种是内存。一般情况将索引放在磁盘上;相应地lucene提供了FSDirectory和RAMDirectory两个类。
* 段:Segment,是Lucene索引文件的最基本的一个单位。Lucene说到底就是不断加入新的Segment,然后按一定的规则算法合并不同的Segment以合成新的Segment。

lucene建立索引的过程就是将待索引的对象转化为Lucene的Document对象,使用IndexWriter将其写入lucene 自定义格式的索引文件中。

待索引的对象可以来自文件、数据库等任意途径,用户自行编码遍历目录读取文件或者查询数据库表取得ResultSet,Lucene的API只负责和字符串打交道。
1.1 Field 的解释

从源代码中,可以看出Field 构造函数如下:

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。其中

* Field.Index有四个属性,分别是:
Field.Index.TOKENIZED:分词索引
Field.Index.UN_TOKENIZED:分词进行索引,如作者名,日期等,Rod Johnson本身为一单词,不再需要分词。
Field.Index:不进行索引,存放不能被搜索的内容如文档的一些附加属性如文档类型, URL等。
Field.Index.NO_NORMS:;
* Field.Store也有三个属性,分别是:
Field.Store.YES:索引文件本来只存储索引数据, 此设计将原文内容直接也存储在索引文件中,如文档的标题。
Field.Store.NO:原文不存储在索引文件中,搜索结果命中后,再根据其他附加属性如文件的Path,数据库的主键等,重新连接打开原文,适合原文内容较大的情况。
Field.Store.COMPRESS 压缩存储;
* termVector是Lucene 1.4.3新增的它提供一种向量机制来进行模糊查询,很少用。

上面所说的Field属性与lucene1.4.3版本的有比较大的不同,在旧版的1.4.3里lucene是通过Field.Keyword (...),FieldUnIndexed(...),FieldUnstored(...)和Field.Text(...)来设置不同字段的类型以达 到不同的用途,而当前版本由Field.Index和Field.Store两个字段的不同组合来达到上述效果。
还有一点说明,其中的两个构造函数其默认的值为Field.Store.NO和Field.Index.TOKENIZED。:

Field(String name, Reader reader)
Field(String name, Reader reader, Field.TermVector termVector)

* 限制Field的长度:
IndexWriter类提供了一个setMaxFieldLength的方法来对Field的长度进行限制,看一下源代码就知道其默认值为10000; 我们可以在使用时重新设置此参数。如果使用默认值,那么Lucene就仅仅对文档的前面的10000个term进行索引,超过这一个数的文档就不会被建立 索引。

1.2 索引的合并、删除、优化

* IndexWriter中的addIndexes方法将索引进行合并;当在不同的地方创建了索引后,如果需要将索引合并,这时候使用addIndexes方法就显得很有意义。
* 可以通过IndexReader类从索引中进行文档的删除。IndexReader是很特别的一个类,看源代码就知道它主要是通过自身的静态方法来完成构造的。示例:

IndexReader reader = IndexReader.open("C:\\springside");
reader.deleteDocument(X); //这里的X是一个int的常数;不推荐这一种删除方法
reader.deleteDocument(new Term("name","springside"));//这是另一种删除索引的方法,按字段来删除,推荐使用这一种做法
reader.close();

* 优化索引:可以使用IndexWriter类的optimize方法来进行优先,它会将多个Segment进行合并,组成一个新的Segment,可以加 快建立索引后搜索的速度。另外需要注意的一点,optimize方法会降低建立索引的速度,而且要求的磁盘空间会增加。

2. 进行搜索时最常用的几个术语

* IndexSearcher:是lucene中最基本的检索工具,所有的检索都会用到IndexSearcher工具。初始化IndexSearcher需要设置索引存放的路径,让查询器能定位索引而进行搜索。
* Query:查询,lucene中支持模糊查询,语义查询,短语查询,组合查询等等,如有TermQuery,BooleanQuery,RangeQuery,WildcardQuery等一些类。
* QueryParser: 是一个解析用户输入的工具,可以通过扫描用户输入的字符串,生成Query对象。
* Hits:在搜索完成之后,需要把搜索结果返回并显示给用户,只有这样才算是完成搜索的目的。在lucene中,搜索的结果的集合是用Hits类的实例来表示的。Hits对象中主要方法有:

length(): 返回搜索结果的总数,下面简单的用法中有用到Hit的这一个方法
doc(int n): 返回第n个文档
iterator(): 返回一个迭代器

这里再提一下Hits,这也是Lucene比较精彩的地方,熟悉hibernate的朋友都知道hibernate有一个延迟加载的属性,同样, Lucene也有。Hits对象也是采用延迟加载的方式返回结果的,当要访问某个文档时,Hits对象就在内部对Lucene的索引又进行一次检索,最后 才将结果返回到页面显示。

3. 一个简单的实例:

首先把lucene的包放在classpath路径中去,写下面一个简单的类:

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 springside 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.addDocument(doc1);
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("springside");
hits = searcher.search(query);
System.out.println("查找\"springside\" 共" + hits.length() + "个结果");

}
}

执行的结果:

查找"lighter" 共2个结果
查找"springside" 共1个结果

4. 一个复杂一点的实例

* 在windows系统下的的C盘,建一个名叫s的文件夹,在该文件夹里面随便建三个txt文件,随便起名啦,就叫"1.txt","2.txt"和"3.txt"啦
其中1.txt的内容如下:

springside社区
更大进步,吸引更多用户,更多贡献 
2007年

而"2.txt"和"3.txt"的内容也可以随便写几写,这里懒写,就复制一个和1.txt文件的内容一样吧

* 下载lucene包,放在classpath路径中,然后建立索引:

/**
* author lighter date 2006-8-7
*/
public class LuceneExample {
public static void main(String[] args) throws Exception {

File fileDir = new File("c:\\s"); // 指明要索引文件夹的位置,这里是C盘的S文件夹下 
File indexDir = new File("c:\\index"); // 这里放索引文件的位置
File[] textFiles = fileDir.listFiles();

Analyzer luceneAnalyzer = new StandardAnalyzer();
IndexWriter indexWriter = new IndexWriter(indexDir,luceneAnalyzer,true);
indexFile(luceneAnalyzer,indexWriter, textFiles); 
indexWriter.optimize();//optimize()方法是对索引进行优化
indexWriter.close(); 
}

public static void indexFile(Analyzer luceneAnalyzer,IndexWriter indexWriter,File[] textFiles) throws Exception
{
//增加document到索引去
for (int i = 0; i < textFiles.length; i++) {
if (textFiles[i].isFile() && textFiles[i].getName().endsWith(".txt")) {
String temp = FileReaderAll(textFiles[i].getCanonicalPath(),"GBK");
Document document = new Document();
Field FieldBody = new Field("body", temp, Field.Store.YES,Field.Index.TOKENIZED);
document.add(FieldBody);
indexWriter.addDocument(document);
}
}
}
public static String FileReaderAll(String FileName, String charset)throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(
new FileInputStream(FileName), charset));
String line = "";
String temp = "";
while ((line = reader.readLine()) != null) {
temp += line;
}
reader.close();
return temp;
}
}

* 执行查询:

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 个结果!

5、Hibernate与lucene的结合使用:

转载于:https://blog.51cto.com/zhoujiyu/200050

Lucene的一些基本使用方法和概念 (JAVA)相关推荐

  1. 决策理论与方法——决策概念与分类

    决策理论与方法--决策概念与分类 决策方法与理论是管理学.领导学的一门核心课程,他们的核心目的是为了 实现科学决策.如果你是零基础,也想自学这门课,我们就一起吧.我想我们会像一个行道树一样,蔓生出很多 ...

  2. java基础之类、对象、实例、属性、方法等概念理解

    在之前的文章里,讲过一些java基础概念,并写了一个简单的java入门代码,通过这些代码,对类和方法的定义做了部分说明. java基础介绍及第一个java程序 如果是了解java的同学,可能就没什么问 ...

  3. 第四节 结构化分析方法的概念

    结构化分析方法的概念 1.软件开发方法学 2.结构化方法的组成 2.1结构化分析方法 2.2结构化设计方法 2.3 结构化程序设计方法 3.结构化分析 结构:是指系统内各个组成要素之间的相互联系.相互 ...

  4. 研究方法的概念和定义格式。

    方法的概念: 就是将一个功能代码抽取出来,把该功能代码单独定义在一个大括号内,形成一个单独的功能.main方法,里面封装我们写的功能代码.方法是一个独立的功能单元. 为什么要用方法? 方法可以把相同的 ...

  5. 46栈内存溢出、内存区域(程序计数器、Java 虚拟机栈、本地方法栈、Java 堆、方法区、直接内存、内存溢出)与内存溢出(对象实例化分析)

    46.什么情况下会发生栈内存溢出 46.1.Java 内存区域与内存溢出 46.1.1.内存区域 46.1.1.1.程序计数器 46.1.1.2.Java 虚拟机栈 46.1.1.3.本地方法栈 46 ...

  6. java语言say方法,简单了解Java方法的定义和使用实现详解

    简单了解Java方法的定义和使用实现详解 发布时间:2020-09-25 11:36:07 来源:脚本之家 阅读:78 作者:OLIVER_QIN 这篇文章主要介绍了简单了解Java方法的定义和使用实 ...

  7. native关键字(本地方法)、 java调用so动态链接库

    Java native关键字 一. 什么是Native Method    简单地讲,一个Native Method就是一个java调用非java代码的接口.一个Native Method是这样一个j ...

  8. 从几个sample来学习Java堆,方法区,Java栈和本地方法栈

    2019独角兽企业重金招聘Python工程师标准>>> 最近在看<深入理解Java虚拟机>,书中给了几个例子,比较好的说明了几种OOM(OutOfMemory)产生的过程 ...

  9. java 同步的方法_关于Java中的同步方法

    我有一个关于Java中方法同步的问题. 考虑一个具有3个同步方法的类. class MyClass{ public synchronized void methodA(){ ... } public ...

最新文章

  1. 对比学习还能这样用:字节推出真正的多到多翻译模型mRASP2
  2. 基于软件开发对嵌入式开发的思考
  3. python 加注拼音-Python 获取中文字拼音首个字母的方法
  4. 宇宙第一 IDE Visual Studio 2019 正式发布
  5. linux gitlab 9 邮件不发送,gitlab无法发送邮件
  6. eclipse连接Mysql和测试
  7. 如何修改ECShop发货单查询显示个数
  8. oracle别名用双引号,Oracle别名大小写 -----解决方案
  9. Bourbon: 让你的sass更简洁
  10. 秒杀面试 - 程序员面试宝典
  11. C语言常见题目汇总(不断更新)(建议收藏)
  12. GH4169高温合金执行什么标准
  13. C#使用spitter控件分割左右两个panel并可拖动
  14. STM32CubeMX全部版本下载地址
  15. python文件及目录操作(copytree)
  16. AODV=DSR+DSDV
  17. 【Bandit Algorithms学习笔记】UCB算法的理论证明
  18. jQuery使用ajaxSubmit()提交表单以及AjaxSubmit的一些用法
  19. 自动秘钥密码(Autokey)
  20. 绝了!毕业10年年薪百万,今天总结一下我都学了什么!

热门文章

  1. 玩转 React(四)- 创造一个新的 HTML 标签
  2. Java java.lang.SecurityException: Prohibited package name
  3. 子进程无法从标准输入读取数据
  4. HDU5248:序列变换(二分)
  5. 基于http协议的api接口对于客户端的身份认证方式以及安全措施[转]
  6. VMware虚拟机中CentOS网络设置
  7. 学习Java,容易被你忽略的小细节(2)
  8. 城管威逼交警“让老百姓笑话”
  9. spring cloud 总结
  10. 【agc004f】Namori Grundy