java之全文索引搜索lucene之增删改查文档与中文分词搜索

接上文,接下来介绍一个lucene的各种query,然后介绍一下中文全文索引搜索。

对于各种query,我就直接上代码了,具体的话,我已经在代码里面注释了,而且关于lucene的执行流程在上文我也已经介绍过了,下面就不废话了。当然啦,我在这里使用过程采用的是java单元测试!

使用之前需要通过这么一些数据建立索引器,这些数据可以来这里下载:,下载之后放到D:\\lucene-exercise\\data文件夹下。然后通过下面这段代码建立索引:

package com.steadyjack.lucene01;import java.io.File;
import java.io.FileReader;
import java.nio.file.Paths;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.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;public class Indexer {//写实例private IndexWriter writer;/*** ʵ初始化写实例* @param indexDir*/public Indexer(String indexDir)throws Exception{Directory dir=FSDirectory.open(Paths.get(indexDir));//标准分词器Analyzer analyzer=new StandardAnalyzer();IndexWriterConfig iwc=new IndexWriterConfig(analyzer);writer=new IndexWriter(dir, iwc);}/*** Description:关闭写实例* Date:2017年2月24日 下午9:40:36* Author:debug-steadyjack* @throws Exception*/public void close()throws Exception{writer.close();}/*** Description:建立索引* Author:debug-steadyjack* @param dataDir* @return* @throws Exception*/public int index(String dataDir)throws Exception{File[] files=new File(dataDir).listFiles();for(File f:files){IndexFile(f);}return writer.numDocs();}private void IndexFile(File f)throws Exception {System.out.println("文件全路径: "+f.getCanonicalPath());Document doc=getDocument(f);writer.addDocument(doc);}private Document getDocument(File f)throws Exception{Document doc=new Document();doc.add(new TextField("contents",new FileReader(f)));//TextField一般则表示需要进行分词存储doc.add(new TextField("fileName", f.getName(),Field.Store.YES));doc.add(new TextField("fullPath",f.getCanonicalPath(),Field.Store.YES));return doc;}public static void main(String[] args) {//建立的索引存放的目录-索引器目录String indexDir="D:\\lucene-exercise\\lucene4";//索引所需要的数据所在的目录String dataDir="D:\\lucene-exercise\\data";Indexer indexer=null;int numIndexed=0;long start=System.currentTimeMillis();try {indexer = new Indexer(indexDir);numIndexed=indexer.index(dataDir);} catch (Exception e) {e.printStackTrace();}finally{try {indexer.close();} catch (Exception e) {e.printStackTrace();}}long end=System.currentTimeMillis();System.out.println("一共写入了 "+numIndexed+" 个文档,用时:"+(end-start)+" 毫秒");}}

最终建立的索引目录如下:

下面先介绍一下对指定项进行搜索、对表达式进行搜索域分页搜索:

package com.steadyjack.lucene03;import java.nio.file.Paths;import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;/*** Description:测试搜索-特定项搜索,表达式搜索* Date:2017年2月22日 下午8:59:12* @author debug-steadyjack*/
public class TesSearchQueryParser {private Directory dir;private IndexReader reader;private IndexSearcher is;/*** Description:初始化读取索引器(索引所在地)* Date:2017年2月24日 下午10:09:57* Author:debug-steadyjack* @throws Exception*/@Beforepublic void before()throws Exception{dir=FSDirectory.open(Paths.get("D:\\lucene-exercise\\lucene4"));reader=DirectoryReader.open(dir);is=new IndexSearcher(reader);}@Afterpublic void after()throws Exception{reader.close();}/*** Description:对特定项进行查询-TermQuery* Date:2017年2月24日 下午10:10:59* Author:debug-steadyjack* @throws Exception*/@Testpublic void testTermQuery()throws Exception{String searchField="contents";String q="stempel";Term t=new Term(searchField, q);TermQuery query=new TermQuery(t);TopDocs hits=is.search(query, 10);System.out.println("搜索 "+q+" 匹配到了 "+hits.totalHits+"  个文档");for(ScoreDoc scoreDoc:hits.scoreDocs){Document document=is.doc(scoreDoc.doc);System.out.println(document.get("fullPath"));}}/*** Description:对表达式进行搜索-QueryParser需要进行分词* Date:2017年2月24日 下午10:11:35* Author:debug-steadyjack* @throws Exception*/@Testpublic void testQueryParser()throws Exception{String searchField="contents";String q="java";//标准分词器Analyzer a=new StandardAnalyzer();QueryParser parser=new QueryParser(searchField, a);Query query=parser.parse(q);TopDocs hits=is.search(query, 10);System.out.println("搜索 "+q+" 匹配到了 "+hits.totalHits+"  个文档");for(ScoreDoc scoreDoc:hits.scoreDocs){Document document=is.doc(scoreDoc.doc);System.out.println(document.get("fullPath"));}}/*** Description:模拟了分页搜索* Date:2017年2月24日 下午10:37:38* Author:debug-steadyjack* @throws Exception*/@Testpublic void testPagination()throws Exception{//第几页与每页需要显示的记录数int pageNo=2;int pageSize=2;String searchField="contents";String q="java";//标准分词器Analyzer a=new StandardAnalyzer();QueryParser parser=new QueryParser(searchField, a);Query query=parser.parse(q);TopDocs hits=is.search(query, 100);System.out.println("搜索 "+q+" 匹配到了 "+hits.totalHits+"  个文档");ScoreDoc[] scoreDocs=hits.scoreDocs;/**  搜索 java 匹配到了 7  个文档D:\lucene-exercise\data\SYSTEM_REQUIREMENTS.txtD:\lucene-exercise\data\JRE_VERSION_MIGRATION.txtD:\lucene-exercise\data\README.txtD:\lucene-exercise\data\NOTICE.txtD:\lucene-exercise\data\MIGRATE.txtD:\lucene-exercise\data\LICENSE.txtD:\lucene-exercise\data\CHANGES.txt */int pos=(pageNo-1)*pageSize;for(int i=pos;i<pos+pageSize;i++){ScoreDoc scoreDoc=scoreDocs[i];Document document=is.doc(scoreDoc.doc);System.out.println(document.get("fullPath"));}}}

下面介绍的则是另外存在的各种query:指定项范围搜索、指定数字范围搜索、指定字符串开头搜索:

首先是Indexer:建立索引器

package com.steadyjack.lucene04;import java.nio.file.Paths;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.document.IntField;
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;public class Indexer {private Integer ids[]={1,2,3};private String citys[]={"aingdao","banjing","changhai"};private String descs[]={"Qingdao is b beautiful city.","Nanjing is c city of culture.","Shanghai is d bustling city."};private Directory dir;/*** Description:获取IndexWriter实例* Date:2017年2月24日 下午10:54:38* Author:debug-steadyjack* @return* @throws Exception*/private IndexWriter getWriter()throws Exception{Analyzer analyzer=new StandardAnalyzer(); // 标准分词器IndexWriterConfig iwc=new IndexWriterConfig(analyzer);IndexWriter writer=new IndexWriter(dir, iwc);return writer;}/*** 生成索引* @param indexDir* @throws Exception*/private void index(String indexDir)throws Exception{dir=FSDirectory.open(Paths.get(indexDir));IndexWriter writer=getWriter();for(int i=0;i<ids.length;i++){Document doc=new Document();doc.add(new IntField("id", ids[i], Field.Store.YES));doc.add(new StringField("city",citys[i],Field.Store.YES));doc.add(new TextField("desc", descs[i], Field.Store.YES));writer.addDocument(doc); }writer.close();}public static void main(String[] args) throws Exception {new Indexer().index("D:\\lucene-exercise\\lucene5");}}

下面是各种query的测试:

package com.steadyjack.lucene04;import java.nio.file.Paths;import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.NumericRangeQuery;
import org.apache.lucene.search.PrefixQuery;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermRangeQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.BytesRef;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;/*** Description:组合查询* Date:2017年2月24日 下午10:56:09* @author debug-steadyjack*/
public class SearchTest {private Directory dir;private IndexReader reader;private IndexSearcher is;@Beforepublic void before() throws Exception {dir=FSDirectory.open(Paths.get("D:\\lucene-exercise\\lucene5"));reader=DirectoryReader.open(dir);is=new IndexSearcher(reader);}@Afterpublic void after() throws Exception {reader.close();}/*** Description:指定项范围搜索  - 一般少用* Date:2017年2月24日 下午10:57:00* Author:debug-steadyjack* @throws Exception*/@Testpublic void testTermRangeQuery()throws Exception{//指定搜索域为 desc中 存在从 b开头到 c结尾 的内容的文件TermRangeQuery query=new TermRangeQuery("desc", new BytesRef("b".getBytes()), new BytesRef("c".getBytes()), true, true);TopDocs hits=is.search(query, 10);for(ScoreDoc scoreDoc:hits.scoreDocs){Document doc=is.doc(scoreDoc.doc);System.out.println(doc.get("id"));System.out.println(doc.get("city"));System.out.println(doc.get("desc"));}     }/*** Description:指定数字范围* Date:2017年2月24日 下午10:57:42* Author:debug-steadyjack* @throws Exception*/@Testpublic void testNumericRangeQuery()throws Exception{//指定搜索域为 id中 存在从 1到2 的内容的文件NumericRangeQuery<Integer> query=NumericRangeQuery.newIntRange("id", 1, 2, true, true);TopDocs hits=is.search(query, 10);for(ScoreDoc scoreDoc:hits.scoreDocs){Document doc=is.doc(scoreDoc.doc);System.out.println(doc.get("id"));System.out.println(doc.get("city"));System.out.println(doc.get("desc"));}       }/*** Description:指定字符串开头搜索* Date:2017年2月24日 下午10:58:58* Author:debug-steadyjack* @throws Exception*/@Testpublic void testPrefixQuery()throws Exception{//指定搜索域为 city中 存在前缀为a 的内容的文件PrefixQuery query=new PrefixQuery(new Term("city","a"));TopDocs hits=is.search(query, 10);for(ScoreDoc scoreDoc:hits.scoreDocs){Document doc=is.doc(scoreDoc.doc);System.out.println(doc.get("id"));System.out.println(doc.get("city"));System.out.println(doc.get("desc"));}    }/*** Description:多条件查询(即组合查询) - 比较常用* Date:2017年2月24日 下午10:59:43* Author:debug-steadyjack* @throws Exception*/@Testpublic void testBooleanQuery()throws Exception{BooleanQuery.Builder booleanQuery=new BooleanQuery.Builder();NumericRangeQuery<Integer> query1=NumericRangeQuery.newIntRange("id", 1, 2, true, true);PrefixQuery query2=new PrefixQuery(new Term("city","a"));booleanQuery.add(query1,BooleanClause.Occur.MUST);booleanQuery.add(query2,BooleanClause.Occur.MUST);TopDocs hits=is.search(booleanQuery.build(), 10);for(ScoreDoc scoreDoc:hits.scoreDocs){Document doc=is.doc(scoreDoc.doc);System.out.println(doc.get("id"));System.out.println(doc.get("city"));System.out.println(doc.get("desc"));}  }}

最后,我们介绍一下lucene的常用之处:中文分词全文索引与索引结果高亮显示

首先也是先建立Indexer:索引器

package com.steadyjack.lucene05;import java.nio.file.Paths;import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.IntField;
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;public class Indexer {private Integer ids[]={1,2,3};private String citys[]={"青岛","南京","上海"};private String descs[]={"青岛是一个美丽的城市。","南京是一个有文化的城市。南京是一个文化的城市南京,简称宁,是江苏省会,地处中国东部地区,长江下游,濒江近海。全市下辖11个区,总面积6597平方公里,2013年建成区面积752.83平方公里,常住人口818.78万,其中城镇人口659.1万人。[1-4] “江南佳丽地,金陵帝王州”,南京拥有着6000多年文明史、近2600年建城史和近500年的建都史,是中国四大古都之一,有“六朝古都”、“十朝都会”之称,是中华文明的重要发祥地,历史上曾数次庇佑华夏之正朔,长期是中国南方的政治、经济、文化中心,拥有厚重的文化底蕴和丰富的历史遗存。[5-7] 南京是国家重要的科教中心,自古以来就是一座崇文重教的城市,有“天下文枢”、“东南第一学”的美誉。截至2013年,南京有高等院校75所,其中211高校8所,仅次于北京上海;国家重点实验室25所、国家重点学科169个、两院院士83人,均居中国第三。[8-10] 。","上海是一个繁华的城市。"};private Directory dir;/*** Description:获取IndexWriter实例* Date:2017年2月24日 下午11:04:21* Author:debug-steadyjack* @return* @throws Exception*/private IndexWriter getWriter()throws Exception{//Analyzer analyzer=new StandardAnalyzer(); // 标准分词器SmartChineseAnalyzer analyzer=new SmartChineseAnalyzer(); //中文分词器IndexWriterConfig iwc=new IndexWriterConfig(analyzer);IndexWriter writer=new IndexWriter(dir, iwc);return writer;}/*** Description:生成索引* Date:2017年2月24日 下午11:05:57* Author:debug-steadyjack* @param indexDir* @throws Exception*/private void index(String indexDir)throws Exception{dir=FSDirectory.open(Paths.get(indexDir));IndexWriter writer=getWriter();for(int i=0;i<ids.length;i++){Document doc=new Document();doc.add(new IntField("id", ids[i], Field.Store.YES));doc.add(new StringField("city",citys[i],Field.Store.YES));doc.add(new TextField("desc", descs[i], Field.Store.YES));writer.addDocument(doc);}writer.close();}public static void main(String[] args) throws Exception {new Indexer().index("D:\\lucene-exercise\\lucene6");}}

然后是中文分词搜索与搜索结果高亮显示Searcher:

package com.steadyjack.lucene05;import java.io.StringReader;
import java.nio.file.Paths;import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.highlight.Fragmenter;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
import org.apache.lucene.search.highlight.SimpleSpanFragmenter;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;/*** Description:中文分词 与 搜索结果高亮显示* Date:2017年2月24日 下午11:03:57* @author debug-steadyjack*/
public class Searcher {/*** Description:搜索* Date:2017年2月24日 下午11:06:45* Author:debug-steadyjack* @param indexDir* @param q* @throws Exception*/public static void search(String indexDir,String q)throws Exception{Directory dir=FSDirectory.open(Paths.get(indexDir));IndexReader reader=DirectoryReader.open(dir);IndexSearcher is=new IndexSearcher(reader);// Analyzer analyzer=new StandardAnalyzer(); // 标准分词器SmartChineseAnalyzer analyzer=new SmartChineseAnalyzer();QueryParser parser=new QueryParser("desc", analyzer);Query query=parser.parse(q);long start=System.currentTimeMillis();TopDocs hits=is.search(query, 10);long end=System.currentTimeMillis();System.out.println("匹配 "+q+" ,总共花费"+(end-start)+"毫秒"+"查询到"+hits.totalHits+"个记录");//下面是高亮显示QueryScorer scorer=new QueryScorer(query);Fragmenter fragmenter=new SimpleSpanFragmenter(scorer);SimpleHTMLFormatter simpleHTMLFormatter=new SimpleHTMLFormatter("<b><font color='red'>","</font></b>");Highlighter highlighter=new Highlighter(simpleHTMLFormatter, scorer);highlighter.setTextFragmenter(fragmenter);for(ScoreDoc scoreDoc:hits.scoreDocs){Document doc=is.doc(scoreDoc.doc);System.out.println(doc.get("city"));System.out.println(doc.get("desc"));String desc=doc.get("desc");if(desc!=null){TokenStream tokenStream=analyzer.tokenStream("desc", new StringReader(desc));System.out.println(highlighter.getBestFragment(tokenStream, desc));}}reader.close();}public static void main(String[] args) {String indexDir="D:\\lucene-exercise\\lucene6";String q="南京文明";try {search(indexDir,q);} catch (Exception e) {e.printStackTrace();}}
}

贴一下运行效果:

好了,博文介绍到这里吧,有需要交流的可以在下面留言,或者加我qq:1948831260进行技术交流

java之全文索引搜索lucene之增删改查文档与中文分词搜索相关推荐

  1. 商城项目16_es简介、详解倒排索引、安装es以及kibana、检索es基本信息、增删改查文档

    文章目录 ①. es - 背景.概述.功能.场景 ②. 核心概念 - 索引.类型.文档.映射 ③. es - 详解倒排索引 ④. 安装elasticSearch.kibana 7.4.2 ⑤. 索引操 ...

  2. java jdbc 连接mysql数据库 实现增删改查

    好久没有写博文了,写个简单的东西热热身,分享给大家. jdbc相信大家都不陌生,只要是个搞java的,最初接触j2ee的时候都是要学习这么个东西的,谁叫程序得和数据库打交道呢!而jdbc就是和数据库打 ...

  3. java对mysql的简单操作——增删改查的总结

    增删改查的详细内容可以点击以下链接: java对mysql的简单操作--增加数据 java对mysql的简单操作--删除数据 java对mysql的简单操作--修改数据 java连接mysql5.1教 ...

  4. java map 输入 查询 修改_Mybatis增删改查mapper文件写法详解

    1. 插入 INSERT sql命令(命令里通过#{}获取对象属性) EG: INSERT INTO PRAC_PERSON(p_NAME,P_PASSWORD) VALUES(#{name},#{p ...

  5. html单页面js完成表数据库自动生成带注释的java实体类和简单的增删改查sql

    支持Mysql和Oracle,mybatis和ibatis可选.功能主要还是字符串的拼凑完成的,把用把表信息复制过来或者增加后台,就可以生成简单的增删改查了 临时体验点这里 我也不知道地址什么时候失效 ...

  6. java上安装zookeeper并且实现增删改查

    目录 一..创建Maven工具 二.将Maven的默认配置文件设置为自己下载的配置文件(非必要) 三.在maven文件中导入zookeeper依赖 四.创建增删改查类MyzkTest 五.实现zook ...

  7. SharePoint 2013 搜索SharePoint 特定列和特定文档(自己定义搜索)

    SharePoint 2013 搜索SharePoint 特定列和特定文档 1,操作步骤和图例,因语言和版本号的不同 我尽量使用抓图方式. 2.  In Central Administration, ...

  8. Java 使用List集合实现图书增删改查

    Book.java /*** @Author ꧁ʚVVcatɞ꧂* @Date 2020/6/22 23:47 星期一* @ProjectName Book* @PackageName PACKAGE ...

  9. 使用Java JdbcTemplate对mySQL进行CRUD增删改查操作

    create方法:用字符串拼接构造一个SQL命令:"insert into Student (name, age) values (?, ?)" 然后传入jdbcTemplateO ...

最新文章

  1. 如何利用 Myflash 解析 binlog ?
  2. PHP常用工具函数之手机号相关
  3. ClickHouse【资源分享 01】Linux环境 clickhouse-19.7.3.9 离线安装文件分享(百度云盘)
  4. SpringBoot底层注解-@ConfigurationProperties配置绑定
  5. MYSQL中有时候不得不使用replace()去掉特殊字符,写在这里备用一下
  6. SQL Server 2005 高级程序设计 学习笔记(2)
  7. Android屏幕禁止休眠的方法
  8. 南开大学计算机学院夏令营,2022保研夏令营:南开大学计算机学院云端夏令营通知...
  9. VS2012使用 MSDN教程
  10. 【原创】破解无线路由密码的那些事儿
  11. 【解决】 io.lettuce.core.RedisCommandExecutionException: ERR wrong number of arguments for 'set' command
  12. 2018华东师范软件复试机试
  13. 博纳影业明日上市:于冬陷入与江疏影绯闻 被曝斥资千万买珠宝
  14. dwg格式转换成jpg图片
  15. 朴素和KMP匹配算法(java)
  16. JVM内存模型和性能调优:阿里巴巴Arthas调优工具:什么是Arthas- 第43篇
  17. **阿里云ECS Linux服务器图形化界面安装方法 Ubuntu**
  18. ip-纯真库:批量获取ip归属地
  19. 计算机械结构变形,机械结构温度变化的位移计算.ppt
  20. 强大的iOS开发必备工具

热门文章

  1. 凡事都得有个度,SEO优化过程的七大忌讳...
  2. githHub使用基础指南
  3. java 中成员变量的名字和类的方法的名字可以一样.
  4. 看看OpenHarmony编译出的镜像中都有啥
  5. 机器学习代码实现:多元线性回归(梯度下降法)吴恩达课后题目
  6. MEMS 陀螺仪抗震动
  7. 三星掐住弱点锁喉,台积电危矣
  8. 定理在数学中的简写形式_这些鲜为人知的数学定理,颠覆你的认知!
  9. c语言中四个字节八位字长,C语言中显示变量所占字节数;字节、字、字长;原码、反码、补码...
  10. 为什么Scala这么受欢迎