用到lucene版本为6.3.0版本,利用的分词器为IKAnalyzer分词器,该分词对中文有较好的支持。关于支持lucene的6.xx以上的IkAnalyzer分词jar包下载地址:https://pan.baidu.com/s/1i5DreTZ

密码:2frx

package com.cn.shupu.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.file.Paths; import javax.management.Query; import org.apache.ibatis.javassist.bytecode.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.document.Field;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.index.IndexableFieldType;
import org.apache.lucene.index.LogByteSizeMergePolicy;
import org.apache.lucene.index.LogMergePolicy;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.search.IndexSearcher;
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.BooleanClause.Occur;
import org.apache.lucene.search.highlight.Fragmenter;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.InvalidTokenOffsetsException;
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.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.BytesRef;
import org.apache.xmlbeans.impl.store.Path;
import org.wltea.analyzer.lucene.IKAnalyzer; public class LuceneUtils { // 索引文件的存放路径
private static String indexPath = "D://index/path"; // 要索引的文件(假如要索引的文件类型为txt文件)
private static String tarPath = "D://font//管理学(第四版).txt"; // 创建索引的方法
public static void createIndex() { File filDir = new File(tarPath); File idnexDir = new File(indexPath); Boolean create = true; if (!idnexDir.exists()) {
idnexDir.mkdirs();
} // 创建文件索引
try {
Directory directroy = FSDirectory.open(Paths.get(indexPath));
// 创建内存索引
RAMDirectory ramDirectory = new RAMDirectory(); // 创建分词器
// 1.创建 SmartChineseAnalyze分词器
// SmartChineseAnalyzer analyzer=new SmartChineseAnalyzer();
// 2.创建StantdarAnalyzer
// StandardAnalyzer analyzer = new StandardAnalyzer(); // 3.创建IKAnalyzer
IKAnalyzer analyzer = new IKAnalyzer(); // 尚未初始化,因为第一次执行分词的时候才会初始化,为了在执行分此前手动添加额外的字典,需要先手动的初始化一下
/*
* Configuration cfg = DefaultConfig.getInstance(); // 加载词库
* cfg.setUseSmart(true); // 设置智能分词
* org.wltea.analyzer.dic.Dictionary.initial(cfg);
*
* org.wltea.analyzer.dic.Dictionary dictionary =
* org.wltea.analyzer.dic.Dictionary.getSingleton();
*
* List<String> newWords = new ArrayList<>();
*
* for (BaseLib book : books) {
*
* newWords.add(book.getName());
*
* } dictionary.addWords(newWords);// 自动添加自定义分词
*/
// 创建索引器之前的初始化
IndexWriterConfig iwc = new IndexWriterConfig(analyzer);
IndexWriterConfig rwc = new IndexWriterConfig(analyzer); // SetMergeFactor是控制segment合并频率的,其决定了一个索引块中包括多少个文档,当硬盘上的索引块达到多少时,
// 将它们合并成一个较大的索引块。当MergeFactor值较大时,生成索引的速度较快。MergeFactor的默认值是10,建议在建立索引前将其设置的大一些。
LogMergePolicy mergePolicy = new LogByteSizeMergePolicy();
mergePolicy.setMergeFactor(100);
iwc.setMergePolicy(mergePolicy);
iwc.setRAMBufferSizeMB(2048);
iwc.setMaxBufferedDocs(1000);
iwc.setMaxBufferedDocs(1000); if (create) {
// Create a new index in the directory, removing any
// previously indexed documents:
// 在目录中创建一个新的索引,删除任何先前生成的索引文档
rwc.setOpenMode(OpenMode.CREATE); } else {
// Add new documents to an existing index:
// 新文档添加到一个现有的指数
rwc.setOpenMode(OpenMode.CREATE_OR_APPEND);
} // 文件索引生成器
IndexWriter fileWriter = new IndexWriter(directroy, iwc); // 内存索引生成器
IndexWriter ramWriter = new IndexWriter(ramDirectory, rwc); // 现将索引添加到内存索引中 // 创建文档
Document document = new Document(); // 添加term,term为索引文件中最小的单位,就像数据库中每一表的field。 // 获取文件的内容
String content = getTxt(filDir); // 其中Store.YESb表示索引的内容要保存的,Store.NO表示索引内容只索引不保存 document.add(new TextField("path", filDir.getAbsolutePath(), Store.YES)); document.add(new TextField("content", content, Store.YES)); // 根据文件的初始的OpenMode来对文件索引的添加或修改
if (ramWriter.getConfig().getOpenMode() == OpenMode.CREATE) { System.out.println("adding " + filDir.getAbsolutePath()); ramWriter.addDocument(document); } else { System.out.println("updating " + filDir.getAbsolutePath());
ramWriter.updateDocument(new Term("path", filDir.toString()), document);
} ramWriter.close(); // 将内存索引添加文件索引中,永久保存。内存索引只是暂时的保存索引文件,当程序结束时,内存索引的文件会消失
fileWriter.addIndexes(new Directory[] { ramDirectory });
fileWriter.forceMerge(1000);
fileWriter.maybeMerge();
fileWriter.close(); } catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } /**
* 121 * 读取txt文件的内容 122 * @param file 想要读取的文件对象 123 * @return 返回文件内容 124
*/
public static String getTxt(File file) {
String result = "";
try {
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), "GBK"));
String s = null;
while ((s = br.readLine()) != null) {// 使用readLine方法,一次读一行 result = result + "\n" + s; }
br.close();
} catch (Exception e) {
e.printStackTrace();
}
return result;
} public static void searchByKeyWord(String keyWord) { try {
Directory directory = FSDirectory.open(Paths.get(indexPath)); // 采用IkAnalyzer,其中true为智能分词。
IKAnalyzer analuzer = new IKAnalyzer(true); // 创建索引的读器
IndexReader ireader = DirectoryReader.open(directory);
// 创建索引的搜索器
IndexSearcher isearcher = new IndexSearcher(ireader); String[] stringQuery = { keyWord, keyWord };// 查询关键词的数组 String[] fields = { "path", "content" };// 多字段查询的值域 // Occur.MUST表示对应字段必须有查询值, Occur.MUST_NOT
// 表示对应字段必须没有查询值,Occur.SHOULD表示对应字段应该存在查询值(但不是必须)
Occur[] occ = { Occur.SHOULD, Occur.SHOULD }; org.apache.lucene.search.Query query = null;
try {
query = MultiFieldQueryParser.parse(stringQuery, fields, occ, analuzer);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/*
* // 只对content进行检索 QueryParser parser = new QueryParser("contents",
* analyzer);
*
* Query query = parser.parse(text);
*/ // 排序
SortField sf = new SortField(keyWord, SortField.Type.STRING_VAL, true); Sort sort = new Sort(sf); int count; // 获取一共多少条数据
TopDocs docs = null;
ScoreDoc[] hits = null;
docs = isearcher.search(query, Integer.MAX_VALUE, sort);
hits = docs.scoreDocs;
// 假如用到分页的时候,用 docs =
// isearcher.searchAfter(results.scoreDocs[page.getAfterDocId()],
// query, page.getPagesize(), sort); for (int i = 0; i < hits.length; i++) {
Document doc = isearcher.doc(hits[i].doc); System.out.println("文件路径:" + doc.get("path")); String content = doc.get("content");
// 查询字段高亮操作 其中100为字符长度可以自动修改的;
String s = null;
try {
s = displayHtmlHighlight(query, analuzer, "content", content, 290);
} catch (InvalidTokenOffsetsException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("内容:" + s); } ireader.close();
directory.close(); } catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } /**
* 获取高亮显示结果的html代码
*
* @param query
* 查询
* @param analyzer
* 分词器
* @param fieldName
* 域名
* @param fieldContent
* 域内容
* @param fragmentSize
* 结果的长度(不含html标签长度)
* @return 结果(一段html代码)
* @throws IOException
* @throws InvalidTokenOffsetsException
*/
static String displayHtmlHighlight(org.apache.lucene.search.Query query,
org.apache.lucene.analysis.Analyzer analyzer, String fieldName, String fieldContent, int fragmentSize)
throws IOException, InvalidTokenOffsetsException {
// 创建一个高亮器
Highlighter highlighter = new Highlighter(new SimpleHTMLFormatter("<font color='red'>", "</font>"),
new QueryScorer(query));
Fragmenter fragmenter = new SimpleFragmenter(fragmentSize);
highlighter.setTextFragmenter(fragmenter);
return highlighter.getBestFragment(analyzer, fieldName, fieldContent);
} public static void main(String[] args) {
//本Demo只对txt文件类型做的索引
createIndex();
searchByKeyWord("管理"); } }

全文检索的Demo的更多相关文章

  1. Apache Lucene(全文检索引擎)—分词器

    目录 返回目录:http://www.cnblogs.com/hanyinglong/p/5464604.html 本项目Demo已上传GitHub,欢迎大家fork下载学习:https://gith ...

  2. Apache Lucene(全文检索引擎)—创建索引

    目录 返回目录:http://www.cnblogs.com/hanyinglong/p/5464604.html 本项目Demo已上传GitHub,欢迎大家fork下载学习:https://gith ...

  3. 全文检索原理以及es

    最近要做个文章搜索,对全文检索原理以及es原理进行了一些调研, 1.  es索引文件为多个文本文件描述,索引文件中的内容构成可见 http://elasticsearch.cn/article/86 ...

  4. 【手把手教你全文检索】Lucene索引的【增、删、改、查】

    前言 搞检索的,应该多少都会了解Lucene一些,它开源而且简单上手,官方API足够编写些小DEMO.并且根据倒排索引,实现快速检索.本文就简单的实现增量添加索引,删除索引,通过关键字查询,以及更新索 ...

  5. SOLR (全文检索)

    SOLR (全文检索) http://sinykk.iteye.com/ 1.   什么是SOLR 官方网站 http://wiki.apache.org/solr http://wiki.apach ...

  6. oracle 全文检索

    一.使用 sys 用户登录oracle (1)运行—cmd—sqlplus — sys/密码 @连接字符 as sysdba 二.授权 1.grant ctxapp to 全文检索使用用户: 2.gr ...

  7. Lucene全文检索(一)

    全文检索的概念 1.从大量的信息中快速.准确的查找要的信息2.收索的内容是文本信息3.不是根据语句的意思进行处理的(不处理语义)4.全面.快速.准确是衡量全文检索系统的关键指标.5.搜索时英文不区分大 ...

  8. Lucene搜索引擎例子demo

    一.导入相应的jar包 KAnalyzer3.2.0Stable.jar lucene-analyzers-3.0.1.jar lucene-core-3.0.1.jar lucene-highlig ...

  9. 全文检索Lucene (2)

    接着全文检索Lucene (1) . 下面我们来深入的研究一下,如何使用Lucene! 从全文检索Lucene (1)中我们可以看出,Lucene就好比一个双向的工作流,一方面是对索引库的维护,另一方 ...

随机推荐

  1. git忽略某些文件的几种方法

    不知道为什么我记得我写过这个内容但是又找不到了,只好照着大致记忆写一下以备留存. 1.首先肯定是.gitignore文件 .gitignore文件适合在文件尚未被追踪时加入,将其忽略便可以不上传到远程 ...

  2. np.meshgrid()用法+ np.stack()用法

    A,B,C,D,E,F是6个网格点,坐标如图,如何用矩阵形式(坐标矩阵)来批量描述这些点的坐标呢?答案如下 这就是坐标矩阵——横坐标矩阵X XX中的每个元素,与纵坐标矩阵Y YY中对应位置元素,共同构 ...

  3. java 常用的异常处理

    在Java中异常被当做对象来处理,根类是java.lang.Throwable类,在Java中定义了很多异常类(如OutOfMemoryError.NullPointerException.Index ...

  4. 51Nod 1058 N的阶乘的长度

    输入N求N的阶乘的10进制表示的长度.例如6! = 720,长度为3.   Input 输入N(1 <= N <= 10^6) Output 输出N的阶乘的长度 Input示例 6 Out ...

  5. Mybaties 实现批量修改

    通常我们在做批量更新的时候都会用in 去操作,但in的数据量一上来,就变的缓慢了 修改方案: <update id="updateShufflingSeq" paramete ...

  6. 剑指offer(37)数字在排序数组中出现的次数。

    题目描述 统计一个数字在排序数组中出现的次数. 题目分析 这题用暴力解也可以过,不过面试官肯定期待更好的解法. 查找我们最熟悉的就是二分查找了,不过二分查找查找的数在数组中只有一个,我们这里却有很多个 ...

  7. Pandas 基础(8) - 用 concat 组合 dataframe

    以各个城市的天气为例, 先准备下面的数据: 印度天气的相关信息: import pandas as pd india_weather = pd.DataFrame({ 'city': ['mumbai ...

  8. CentOS7.4安装jdk1.8.0_201、Tomcat-8.5.38环境

    有时候安装一些软件或者服务都需要jdk环境,今天就在centos1.4上安装最新的jdk环境. 检测历时安装 1.查看Linux自带的JDK是否已安装 # java -version 2.查看JDK信 ...

  9. Ceph常用命令

    目录 [1.环境准备] [2.部署管理] [3.集群扩容] [4.用户管理] [5.密钥环管理] [6.块设备管理] [7.快照管理] [8.参考链接] 简要说明: 最近心血来潮,对分布式存储感兴趣, ...

  10. inline-block间隙问题总结, ,style一个样式后面 多加了一个 分号; 导致 样式失效

    1--- 样式最后的{}后面, 不能有分号 ; 2---- display:inline-block 后, 元素间会有间隙    原因:  由换行或者回车导致的. 解决一: 只要把标签写成一行或者标签 ...