lucene 学习之编码篇
本文环境:lucene5.2 JDK1.7 IKAnalyzer
引入lucene相关包
<!-- lucene核心包 -->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
<version>5.2.0</version>
</dependency>
<!-- 查询解析器 -->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-queryparser</artifactId>
<version>5.2.0</version>
</dependency>
<!-- 分词器 -->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-common</artifactId>
<version>5.2.0</version>
</dependency>
开发中依赖的包
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency> <!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
一、创建索引
1、确定索引库的位置
a、将索引库存入本地磁盘
FSDirectory dir=FSDirectory.open(path);
b、将索引存入内存
Directory directory = new RAMDirectory();
2、创建分词器
//创建分词器
Analyzer al=new StandardAnalyzer();
lucene内置有四个分析器:WhitespaceAnalyzer、SimpleAnalyzer、StopAnalyser、StandardAnalyzer
- WhitespaceAnalyzer:分析器是通过空格来分割文本信息
- SimpleAnalyzer:分析器会首先通过非字母字符来拆分文本信息,并统一转为小写格式,会去掉数字类型的字符
- StopAnalyser:和SimpleAnalyzer分析器类似,但StopAnalyser会去掉一些常用单词(the、a、an..)
- StandardAnalyzer:是lucene最复杂的核心分析器,可以识别某些种类的语汇单元,如公司名称、Email、主机名称等,它会将语汇单元转为小写格式,并去除掉停用词和标点符号
3、创建IndexWriter,进行索引文件的写入。
//创建索引的写入配置对象
IndexWriterConfig iwc= new IndexWriterConfig(al);
//创建索引的Writer
IndexWriter iw=new IndexWriter(dir, iwc);
4、创建文档 创建域将内容提取并进行索引的存储
//创建文档
Document doc=new Document();
//创建域 (域是键值对的数据结构)Store.YES:将该值存储到索引库
Field fieldName=new TextField("fieldName","xs.txt",Store.YES);
Field fieldContent=new TextField("fieldContent","san guo yan yi",Store.YES);
Field fieldsize=new LongField("fieldSize",10324,Store.YES);
Field fieldPath=new TextField("fieldPath","F:/xs/sg/xs.txt",Store.YES);
//将域加入文档中
doc.add(fieldName);
doc.add(fieldContent);
doc.add(fieldsize);
doc.add(fieldPath);
//把文档写入索引库
iw.addDocument(doc);
Field域的3各重要属性:
a、是否分析
将field值按照指定的分词器进行分析出相应的语汇单元,将词进行索引。例如:博文标题、博文作者、博文描述、博文内容 ,这些都应该建立索引
b、是否索引
对field分析后的词或整个field值进行索引,只有建立索引的field才能被搜索
c、是否存储(Store.YES:表示存储 Store.NO:表示不存储)
将field值存储在文档中,只有存储在文档中的field才可以从Document中取出。(一般对于内容较大的field不建立存储)
常用Field域的类型:
5、提交,并关闭资源
//提交
iw.commit();
iw.close();
完整代码:
@Test
public void ImportIndex() throws IOException {
//获得索引库路径
Path path=Paths.get("E:\\test\\luceneWI");
//打开索引库
FSDirectory dir=FSDirectory.open(path);
//创建分词器
Analyzer al=new StandardAnalyzer();
//创建索引的写入配置对象
IndexWriterConfig iwc= new IndexWriterConfig(al);
//创建索引的Writer
IndexWriter iw=new IndexWriter(dir, iwc);
//采集原始文档
File sourceFile=new File("E:\\test\\lucene");
//获取该文件下所有的文件
File [] files=sourceFile.listFiles();
//遍历每一个文件
for(File file:files){
//获取文件属性
String fileName=file.getName();
String content=FileUtils.readFileToString(file);
long size=FileUtils.sizeOf(file);
String sourcePath=file.getPath();
//创建文档
Document doc=new Document();
//创建域 (域是键值对的数据结构)Store.YES:将该值存储到索引库
Field fieldName=new TextField("fieldName",fileName,Store.YES);
Field fieldContent=new TextField("fieldContent",content,Store.YES);
Field fieldsize=new LongField("fieldSize",size,Store.YES);
Field fieldPath=new TextField("fieldPath",sourcePath,Store.NO);
//将域加入文档中
doc.add(fieldName);
doc.add(fieldContent);
doc.add(fieldsize);
doc.add(fieldPath);
//把文档写入索引库
iw.addDocument(doc);
}
//提交
iw.commit();
iw.close();
}
执行结果查看索引库
我们使用 luke可以查看索引库的具体信息luke-5.3.0-luke-release
二、添加索引
添加前我们的索引库中有7各文档
现在我们要新加一条文档
@Test
public void addIndex() throws IOException {
//获得索引库路径
Path path=Paths.get("E:\\test\\luceneWI");
//打开索引库
FSDirectory dir=FSDirectory.open(path);
//创建分词器
Analyzer al=new IKAnalyzer();
//创建索引的写入配置对象
IndexWriterConfig iwc= new IndexWriterConfig(al);
//创建索引的Writer
IndexWriter iw=new IndexWriter(dir, iwc);
//新建一个文件 china.txt
File file=new File("E:\\test\\lucene\\china.txt");
String fileName=file.getName();
String content=FileUtils.readFileToString(file);
long size=FileUtils.sizeOf(file);
String sourcePath=file.getPath();
//创建域 (域时键值对的数据结构)Store.YES:在索引库中是否以存储的形式存在
Field fieldName=new TextField("fieldName",fileName,Store.YES);
Field fieldContent=new TextField("fieldContent",content,Store.YES);
Field fieldsize=new LongField("fieldSize",size,Store.YES);
Field fieldPath=new TextField("fieldPath",sourcePath,Store.YES);
//创建文档
Document doc=new Document();
//将域加入文档中
doc.add(fieldName);
doc.add(fieldContent);
doc.add(fieldPath);
doc.add(fieldsize);
//把文档写入索引库
iw.addDocument(doc);
iw.commit();
iw.close();
}
执行后
三、删除索引
1、删除所有
@Test
public void deleteIndexAll() throws IOException {
//获得索引库路径
Path path=Paths.get("E:\\test\\luceneWI");
//打开索引库
FSDirectory dir=FSDirectory.open(path);
//创建分词器
Analyzer al=new IKAnalyzer();
//创建索引的写入配置对象
IndexWriterConfig iwc= new IndexWriterConfig(al);
//创建索引的Writer
IndexWriter iw=new IndexWriter(dir, iwc);
iw.deleteAll();//删除所有
iw.commit();//提交
iw.close();//关闭资源
}
2、按照条件删除
@Test
public void deleteIndexAllQuery() throws IOException {
//获得索引库路径
Path path=Paths.get("E:\\test\\luceneWI");
//打开索引库
FSDirectory dir=FSDirectory.open(path);
//创建分词器
Analyzer al=new IKAnalyzer();
//创建索引的写入配置对象
IndexWriterConfig iwc= new IndexWriterConfig(al);
//创建索引的Writer
IndexWriter iw=new IndexWriter(dir, iwc);
//创建语汇单元
Term term=new Term("fieldName","china");// 要删除的document中包含的语汇单元
//创建根据语汇单元的查询对象
Query query=new TermQuery(term);
iw.deleteDocuments(query);
iw.commit();//提交
iw.close();//关闭资源
}
四、查询
1、分词语汇单元查询
@Test
public void QueryIndexAll() throws IOException {
//获得索引库路径
Path path=Paths.get("E:\\test\\luceneWI");
//打开索引库
FSDirectory dir=FSDirectory.open(path);
//创建索引库的读取对象
DirectoryReader reader=DirectoryReader.open(dir);
//创建索引库的搜索对象
IndexSearcher is=new IndexSearcher(reader);
//创建语汇单元
Term term=new Term("fieldName","license");// 要删除的document中包含的语汇单元
//创建根据语汇单元的查询对象
TermQuery tq=new TermQuery(term);
TopDocs result=is.search(tq, 10);//查询前10条
int totalHits=result.totalHits;//获取总记录数
System.out.println("totalHits:"+totalHits);
//获取文档列表
ScoreDoc[] sd=result.scoreDocs;
for(ScoreDoc sc:sd){
int id=sc.doc;//获取文档ID
Document doc=is.doc(id);//获取文档
String fieldName=doc.get("fieldName");
String fieldContent=doc.get("fieldContent");
String fieldSize=doc.get("fieldSize");
String fieldPath=doc.get("fieldPath");
System.out.println("fieldName:"+fieldName);
System.out.println("fieldContent:"+fieldContent);
System.out.println("fieldSize:"+fieldSize);
System.out.println("fieldPath:"+fieldPath);
}
}
2、数值范围查询
@Test
public void queryIndexNumberAll() throws IOException {
//获得索引库路径
Path path=Paths.get("E:\\test\\luceneWI");
//打开索引库
FSDirectory dir=FSDirectory.open(path);
//创建索引库的读取对象
DirectoryReader reader=DirectoryReader.open(dir);
//创建索引库的搜索对象
IndexSearcher is=new IndexSearcher(reader);
//创建数值查询对象
Query tq=NumericRangeQuery.newLongRange("fieldSize", 0L, 100L, true, true);
System.out.println("打印查询对象:"+tq);//打印查询对象:fieldSize:[0 TO 100]
TopDocs result=is.search(tq, 10);//查询前10条
int totalHits=result.totalHits;//获取总记录数
System.out.println("totalHits:"+totalHits);
//获取文档列表
ScoreDoc[] sd=result.scoreDocs;
for(ScoreDoc sc:sd){
int id=sc.doc;//获取文档ID
Document doc=is.doc(id);//获取文档
String fieldName=doc.get("fieldName");
String fieldContent=doc.get("fieldContent");
String fieldSize=doc.get("fieldSize");
String fieldPath=doc.get("fieldPath");
System.out.println("fieldName:"+fieldName);
System.out.println("fieldContent:"+fieldContent);
System.out.println("fieldSize:"+fieldSize);
System.out.println("fieldPath:"+fieldPath);
}
}
3、多查询对象联合查询
@Test
public void bqqueryIndexNumberAll() throws IOException {
//获得索引库路径
Path path=Paths.get("E:\\test\\luceneWI");
//打开索引库
FSDirectory dir=FSDirectory.open(path);
//创建索引库的读取对象
DirectoryReader reader=DirectoryReader.open(dir);
//创建索引库的搜索对象
IndexSearcher is=new IndexSearcher(reader);
//创建多条件查询对象,通过控制& 或者| 或者 ! 来组合查询条件
BooleanQuery tq=new BooleanQuery();
//创建分词语汇查询对象
Query query1=new TermQuery(new Term("fieldName","china"));
Query query2=new TermQuery(new Term("fieldContent","china"));
Query query3=NumericRangeQuery.newLongRange("fieldSize", 0L, 100L, true, true);
//通过BooleanQuery 控制 两个查询条件的关系
tq.add(query1,Occur.MUST);
tq.add(query2,Occur.MUST); //Occur.MUST 同时满足 Occur.SHOULD: 可以满足可以不满足 Occur.MUST_NOT:不能满足
tq.add(query3,Occur.MUST);
System.out.println("bq:"+tq);//bq:+fieldName:china +fieldContent:china ( 表示 必须同时满足两个条件)
TopDocs result=is.search(tq, 10);//查询前10条
int totalHits=result.totalHits;//获取总记录数
System.out.println("totalHits:"+totalHits);
//获取文档列表
ScoreDoc[] sd=result.scoreDocs;
for(ScoreDoc sc:sd){
int id=sc.doc;//获取文档ID
Document doc=is.doc(id);//获取文档
String fieldName=doc.get("fieldName");
String fieldContent=doc.get("fieldContent");
String fieldSize=doc.get("fieldSize");
String fieldPath=doc.get("fieldPath");
System.out.println("fieldName:"+fieldName);
System.out.println("fieldContent:"+fieldContent);
System.out.println("fieldSize:"+fieldSize);
System.out.println("fieldPath:"+fieldPath);
}
}
4、解析查询
QueryParser 对查询条件进行分词查询
@Test
public void queryParserIndexAll() throws Exception {
//获得索引库路径
Path path=Paths.get("E:\\test\\luceneWI");
//打开索引库
FSDirectory dir=FSDirectory.open(path);
//创建索引库的读取对象
DirectoryReader reader=DirectoryReader.open(dir);
//创建索引库的搜索对象
IndexSearcher is=new IndexSearcher(reader);
//创建查询解析对象
QueryParser qp=new QueryParser("fieldName", new IKAnalyzer());//分词器要与创建索引的一样
//通过QueryParser解析查询对象
Query tq=qp.parse("爱我china");//单个查询条件
// Query tq=qp.parse("fieldName:爱我 OR fieldContent:china");//多个查询条件 OR /AND
System.out.println("tq:"+tq);//tq:fieldName:爱我 fieldName:我 fieldName:china (进行分词了)
TopDocs result=is.search(tq, 10);//查询前10条
int totalHits=result.totalHits;//获取总记录数
System.out.println("totalHits:"+totalHits);
//获取文档列表
ScoreDoc[] sd=result.scoreDocs;
for(ScoreDoc sc:sd){
int id=sc.doc;//获取文档ID
Document doc=is.doc(id);//获取文档
String fieldName=doc.get("fieldName");
String fieldContent=doc.get("fieldContent");
String fieldSize=doc.get("fieldSize");
String fieldPath=doc.get("fieldPath");
System.out.println("fieldName:"+fieldName);
System.out.println("fieldContent:"+fieldContent);
System.out.println("fieldSize:"+fieldSize);
System.out.println("fieldPath:"+fieldPath);
}
}
5、多域解析查询
@Test
public void queryManyParserIndexAll() throws Exception {
//获得索引库路径
Path path=Paths.get("E:\\test\\luceneWI");
//打开索引库
FSDirectory dir=FSDirectory.open(path);
//创建索引库的读取对象
DirectoryReader reader=DirectoryReader.open(dir);
//创建索引库的搜索对象
IndexSearcher is=new IndexSearcher(reader);
//定义多个域
String [] fields={"fieldName","fieldContent"};
//创建查询解析对象 查询的语汇单词之间的关系是或,只要满足其中一个语汇单元,就可以查询出来
MultiFieldQueryParser mp=new MultiFieldQueryParser(fields, new IKAnalyzer());
Query tq=mp.parse("爱我china");
System.out.println("tq:"+tq);//tq:(fieldName:爱我 fieldName:我 fieldName:china) (fieldContent:爱我 fieldContent:我 fieldContent:china)
TopDocs result=is.search(tq, 10);//查询前10条
int totalHits=result.totalHits;//获取总记录数
System.out.println("totalHits:"+totalHits);
//获取文档列表
ScoreDoc[] sd=result.scoreDocs;
for(ScoreDoc sc:sd){
int id=sc.doc;//获取文档ID
Document doc=is.doc(id);//获取文档
String fieldName=doc.get("fieldName");
String fieldContent=doc.get("fieldContent");
String fieldSize=doc.get("fieldSize");
String fieldPath=doc.get("fieldPath");
System.out.println("fieldName:"+fieldName);
System.out.println("fieldContent:"+fieldContent);
System.out.println("fieldSize:"+fieldSize);
System.out.println("fieldPath:"+fieldPath);
}
}
lucene 学习之编码篇的更多相关文章
- lucene 学习之基础篇
一.什么是全文索引 全文检索首先将要查询的目标文档中的词提取出来,组册索引(类似书的目录),通过查询索引达到搜索目标文档的目的,这种先建立索引,再对索引进行搜索的过程就叫全文索引. 从图可以看出做全文 ...
- 一步步学习javascript基础篇(3):Object、Function等引用类型
我们在<一步步学习javascript基础篇(1):基本概念>中简单的介绍了五种基本数据类型Undefined.Null.Boolean.Number和String.今天我们主要介绍下复杂 ...
- RabbitMQ学习总结 第二篇:快速入门HelloWorld
目录 RabbitMQ学习总结 第一篇:理论篇 RabbitMQ学习总结 第二篇:快速入门HelloWorld RabbitMQ学习总结 第三篇:工作队列Work Queue RabbitMQ学习总结 ...
- PHP学习笔记 - 进阶篇(11)
PHP学习笔记 - 进阶篇(11) 数据库操作 PHP支持哪些数据库 PHP通过安装相应的扩展来实现数据库操作,现代应用程序的设计离不开数据库的应用,当前主流的数据库有MsSQL,MySQL,Syba ...
- PHP学习笔记 - 进阶篇(4)
PHP学习笔记 - 进阶篇(4) 字符串操作 字符串介绍 PHP开发中,我们遇到最多的可能就是字符串. 字符串变量用于包含字符串的值. 一个字符串 通过下面的3种方法来定义: 1.单引号 2.双引号 ...
- Lucene学习总结之七:Lucene搜索过程解析
一.Lucene搜索过程总论 搜索的过程总的来说就是将词典及倒排表信息从索引中读出来,根据用户输入的查询语句合并倒排表,得到结果文档集并对文档进行打分的过程. 其可用如下图示: 总共包括以下几个过程: ...
- Lucene学习总结之六:Lucene打分公式的数学推导
在进行Lucene的搜索过程解析之前,有必要单独的一张把Lucene score公式的推导,各部分的意义阐述一下.因为Lucene的搜索过程,很重要的一个步骤就是逐步的计算各部分的分数. Lucene ...
- Java工程师学习指南 完结篇
Java工程师学习指南 完结篇 先声明一点,文章里面不会详细到每一步怎么操作,只会提供大致的思路和方向,给大家以启发,如果真的要一步一步指导操作的话,那至少需要一本书的厚度啦. 因为笔者还只是一名在校 ...
- Lucene学习总结之七:Lucene搜索过程解析 2014-06-25 14:23 863人阅读 评论(1) 收藏
一.Lucene搜索过程总论 搜索的过程总的来说就是将词典及倒排表信息从索引中读出来,根据用户输入的查询语句合并倒排表,得到结果文档集并对文档进行打分的过程. 其可用如下图示: 总共包括以下几个过程: ...
随机推荐
- linux线程篇 (二) 线程的基本操作
线程 进程 标识符 pthread_t pid_t 获取ID pthread_self() getpid() 创建 pthread_create() fork 销毁 pthread_exit() ...
- 蓝桥杯 算法训练 K好数
参考:https://blog.csdn.net/jjmjeffrey/article/details/69298110 https://www.cnblogs.com/TWS-YIFEI/p/634 ...
- java入门---对象和类&概念详解&实例
Java作为一种面向对象语言.支持以下基本概念: 多态 继承 封装 抽象 类 对象 实例 方法 重载 这篇文章,我们主要来看下: 对象:对象是类的一个实例(对象不是找个女朋友),有状态 ...
- Git项目的目录结构
branch是分支 trunk是主干 bug修正和新功能的添加一般在branch进行 测试好了没问题了就可以合并到trunk 每隔一段时间就可以打包成一个版本放到tags 用于发布的版本一般 ...
- SIFT 特征点提取算法
SIFT特征点相对于ORB计算速度较慢,在没有GPU加速情况下,无法满足视觉里程计的实时性要求,或者无法运行在手机平台上,但是效果更好,精度更高.在应用时可以择优选取,了解其本质原理的动机是为了自己使 ...
- SSM-Spring-23:概念《Spring中的事务是什么?》
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 本篇博客会详细讲述Spring中的事务,会展开来用语言解释,用于了解概念和准备面试 事务的概念: 一个或者一组 ...
- ElasticSearch搜索引擎在JavaWeb项目中的应用
近几篇ElasticSearch系列: 1.阿里云服务器Linux系统安装配置ElasticSearch搜索引擎 2.Linux系统中ElasticSearch搜索引擎安装配置Head插件 3.Ela ...
- ReadyAPI 教程和示例(二)
声明:如果你想转载,请标明本篇博客的链接,请多多尊重原创,谢谢! 本篇使用的 ReadyAPI版本是2.5.0 接上一篇: 4.修改SoapUI测试 本节将演示如何为测试用例添加测试步骤以及更改请求参 ...
- leetcode-单词探索
单词搜索 给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格.同一个单元格内的字母 ...
- 一种跨平台的C++遍历目录的方法
参考了网络上各路大神的实现方法.主要使用了io.h库 #include <iostream> #include <cstring> #include <io.h> ...