今天 用lucene完毕了 一个简单的web应用。提取了早期编写的一个測试类。 首先简单介绍下lucene几个经常使用包;

lucene 包的组成结构:对于外部应用来说索引模块(index)和检索模块(search)是基本的外部应用入口



org.apache.Lucene.search/ 搜索入口 

org.apache.Lucene.index/ 索引入口 

org.apache.Lucene.analysis/ 语言分析器 

org.apache.Lucene.queryParser/ 查询分析器 

org.apache.Lucene.document/ 存储结构 

org.apache.Lucene.store/  底层IO/存储结构 

org.apache.Lucene.util/ 一些公用的数据结构

话不多说,直接上代码(这是早期封装的一个測试类。封装的还算比較完好,有兴趣的朋友能够在此基础上继续完好):

package com.lucene.util;

import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.util.List; import org.apache.log4j.Logger;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.LogDocMergePolicy;
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.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.MatchAllDocsQuery;
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.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.util.NumericUtils;
import org.apache.lucene.util.Version;
import org.wltea.analyzer.lucene.IKAnalyzer; import com.message.base.search.SearchBean; /**
* lucene 4.10.1
*
* @creatTime 2014-10-28
* @author 胡慧超
*
*/
public class HhcIndexTools { private final static Logger logger = Logger.getLogger(HhcIndexTools.class);
private static String indexPath = "E://lucene//index"; public static void main(String[] args) {
try {
// createIndex();
// searchIndex("码农");
// query();
// deleteIndex(null);
forceDeleteIndex();
query();
highlighterSearch();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} /**
* 创建索引
*/
public static void createIndex() {
// 最细粒切分算法--true的话是 智能切分
Analyzer analyzer = new IKAnalyzer(false);
Document doc = null;
IndexWriter indexWriter = null;
try {
indexWriter = getIndexWriter(analyzer);
// 加入索引
doc = new Document();
doc.add(new StringField("id", "1", Store.YES));
doc.add(new TextField("title", "标题:開始", Store.YES));
doc.add(new TextField("content", "内容:我如今是个码农", Store.YES));
indexWriter.addDocument(doc);
doc = new Document();
doc.add(new StringField("id", "2", Store.YES));
doc.add(new TextField("title", "标题:结束", Store.YES));
doc.add(new TextField("content", "内容:我如今是个lucene开发project师的专家",
Store.YES));
indexWriter.addDocument(doc);
indexWriter.commit();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
logger.info("索引器发送异常");
} finally {
try {
destroyWriter(indexWriter);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} /**
* 搜索文档
*
* @param keyword
*/
@SuppressWarnings("deprecation")
public static void searchIndex(String keyword) {
IndexReader indexReader = null;
IndexSearcher indexSearcher = null;
try {
// 1.创建Directory 在硬盘上的F:/luence/index下建立索引
Directory dir = FSDirectory.open(new File(indexPath));
// 2.创建IndexReader
indexReader = IndexReader.open(dir);
// 实例化搜索器
indexSearcher = new IndexSearcher(indexReader); // 使用QueryParser查询分析器构造Query对象
QueryParser parse = new QueryParser(Version.LUCENE_4_10_1,
"content", new IKAnalyzer(false));
// 搜索包括keyword关键字的文档
Query query = parse.parse(keyword.trim()); // 使用lucene构造搜索引擎的时候,假设要针对多个域进行一次性查询
// 这样的方法的优点就是能够加权给字段的控制
// 在这四个域中检索
String[] fields = { "phoneType", "name", "category", "price" };
Query querys = new MultiFieldQueryParser(Version.LATEST, fields,
new IKAnalyzer(false)).parse(keyword.trim()); TopDocs results = indexSearcher.search(query, 1000);
// 6.依据TopDocs获取ScoreDoc对象
ScoreDoc[] score = results.scoreDocs;
if (score.length > 0) {
logger.info("查询结果数:" + score.length);
System.out.println("查询结果数:" + score.length);
for (int i = 0; i < score.length; i++) {
// 7.依据Seacher和ScoreDoc对象获取详细的Document对象
Document doc = indexSearcher.doc(score[i].doc);
// 8.依据Document对象获取须要的值
System.out.println(doc.toString());
System.out.println(doc.get("title") + "["
+ doc.get("content") + "]");
}
} else {
}
} catch (Exception e) {
// TODO: handle exception
logger.info("查询结果为空!");
} finally {
if (indexReader != null) {
try {
indexReader.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} } /**
* 对搜索返回的前n条结果进行分页显示
*
* @param keyWord
* 查询关键词
* @param pageSize
* 每页显示记录数
* @param currentPage
* 当前页
* @throws ParseException
*/
@SuppressWarnings("deprecation")
public void paginationQuery(String keyWord, int pageSize, int currentPage)
throws IOException, ParseException {
String[] fields = { "title", "content" };
QueryParser queryParser = new MultiFieldQueryParser(Version.LATEST,
fields, new IKAnalyzer());
Query query = queryParser.parse(keyWord.trim()); IndexReader indexReader = IndexReader.open(FSDirectory.open(new File(
indexPath)));
IndexSearcher indexSearcher = new IndexSearcher(indexReader); // TopDocs 搜索返回的结果
TopDocs topDocs = indexSearcher.search(query, 100);// 仅仅返回前100条记录
TopDocs all = indexSearcher.search(new MatchAllDocsQuery(), 100);
// int totalCount = topDocs.totalHits; // 搜索结果总数量
ScoreDoc[] scoreDocs = topDocs.scoreDocs; // 搜索返回的结果集合 // 查询起始记录位置
int begin = pageSize * (currentPage - 1);
// 查询终止记录位置
int end = Math.min(begin + pageSize, scoreDocs.length); // 进行分页查询
for (int i = begin; i < end; i++) {
int docID = scoreDocs[i].doc;
System.out.println("docID=" + docID);
Document doc = indexSearcher.doc(docID);
String title = doc.get("title");
System.out.println("title is : " + title);
}
indexReader.close();
} @SuppressWarnings("deprecation")
public static void highlighterSearch() throws IOException, ParseException, InvalidTokenOffsetsException {
IndexReader reader = IndexReader.open(FSDirectory.open(new File(
indexPath)));
IndexSearcher searcher = new IndexSearcher(reader); // String []fields={"title","content"};
// QueryParser parser=new MultiFieldQueryParser(Version.LATEST, fields,
// new IKAnalyzer());
// Query query=parser.parse(""); Term term = new Term("content", "lucene");
TermQuery query = new TermQuery(term); TopDocs topdocs = searcher.search(query, Integer.MAX_VALUE);
ScoreDoc[] scoreDoc = topdocs.scoreDocs;
System.out.println("查询结果总数:" + topdocs.totalHits);
System.out.println("最大的评分:" + topdocs.getMaxScore()); for(int i=0;i<scoreDoc.length;i++){
int docid=scoreDoc[i].doc;
Document document=searcher.doc(docid);
System.out.println("============文件【"+(i+1)+"】=========");
System.out.println("检索关键字:"+term.toString());
String content=document.get("content"); //高亮展示 SimpleHTMLFormatter //
SimpleHTMLFormatter formatter=new SimpleHTMLFormatter("<font color='red'>", "</font>");
Highlighter highlighter=new Highlighter(formatter, new QueryScorer(query));
highlighter.setTextFragmenter(new SimpleFragmenter(content.length())); if(!"".equals(content)){
TokenStream tokenstream=new IKAnalyzer().tokenStream(content, new StringReader(content));
String highLightText = highlighter.getBestFragment(tokenstream,content);
System.out.println("高亮显示第 " + (i + 1) + " 条检索结果例如以下所看到的:");
System.out.println(highLightText);
/*End:结束关键字高亮*/
System.out.println("文件内容:"+content);
System.out.println("匹配相关度:"+scoreDoc[i].score);
}
}
} /**
* 获取indexWriter对象---获取索引器
*
* @param dir
* @param analyer
* @return
* @throws IOException
*/
private static IndexWriter getIndexWriter(Analyzer analyzer)
throws IOException {
File indexFile = new File(indexPath);
if (!indexFile.exists())
indexFile.mkdir();// 索引库不存在 则新建一个
Directory directory = FSDirectory.open(indexFile);
// Directory directory = new RAMDirectory(); //在内存中建立索引 IndexWriterConfig conf = new IndexWriterConfig(Version.LUCENE_4_10_1,
analyzer);
LogMergePolicy mergePolicy = new LogDocMergePolicy();
// 索引基本配置
// 设置segment加入文档(Document)时的合并频率
// 值较小,建立索引的速度就较慢
// 值较大,建立索引的速度就较快,>10适合批量建立索引
mergePolicy.setMergeFactor(30);
// 设置segment最大合并文档(Document)数
// 值较小有利于追加索引的速度
// 值较大,适合批量建立索引和更快的搜索
mergePolicy.setMaxMergeDocs(5000);
conf.setMaxBufferedDocs(10000);
conf.setMergePolicy(mergePolicy);
conf.setRAMBufferSizeMB(64); conf.setOpenMode(OpenMode.CREATE_OR_APPEND);
if (IndexWriter.isLocked(directory)) {// ?
IndexWriter.unlock(directory);
}
IndexWriter indexWriter = new IndexWriter(directory, conf);
return indexWriter;
} /**
* 销毁writer
*
* @param writer
* @throws IOException
*/
private static void destroyWriter(IndexWriter indexWriter)
throws IOException {
if (indexWriter != null) {
indexWriter.close();
}
} /**
* 批量删除
*
* @param list
* @throws IOException
*/
public static void deleteIndexs(List<SearchBean> list) throws IOException {
if (list == null || list.size() > 0) {
logger.debug("beans is null");
return;
}
for (SearchBean bean : list) {
deleteIndex(bean);
}
} /**
* 删除单个索引 --不会立马删除,生成.del文件
*
* @param bean
* @throws IOException
*/
private static void deleteIndex(SearchBean bean) throws IOException {
// if(bean==null){
// logger.debug("Get search bean is empty!");
// return;
// }
IndexWriter indexWriter = getIndexWriter(new IKAnalyzer());
// 參数是一个选项,能够是一个Query,也能够是一个term,term是一个精确查找的值
// 这里删除id=1的文档,还会留在”回收站“。xxx.del
indexWriter.deleteDocuments(new Term("id", "1"));
destroyWriter(indexWriter);
} /**
* 查询文档
*/
@SuppressWarnings("deprecation")
public static void query() {
// 1.创建Directory 在硬盘上的F:/luence/index下建立索引
try {
IndexReader indexReader = IndexReader.open(FSDirectory
.open(new File(indexPath)));
System.out.println("存储的文档数:" + indexReader.numDocs());
System.out.println("总存储量:" + indexReader.maxDoc());
System.out.println("被删除的文档:" + indexReader.numDeletedDocs());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} /**
* 回滚回收站
*
* @throws IOException
*/
public void recoveryIndexByIsDelete() throws IOException {
IndexWriter indexWriter = getIndexWriter(new IKAnalyzer());
indexWriter.rollback();
destroyWriter(indexWriter);
} /**
* 清空回收站 在版本号3.6之后,已经没有了unDeleteAll()方法了
*
* @throws IOException
*/
public static void forceDeleteIndex() throws IOException {
IndexWriter indexWriter = getIndexWriter(new IKAnalyzer());
indexWriter.forceMergeDeletes();
destroyWriter(indexWriter);
} /**
* 更新索引
*
* @throws IOException
*/
public void update() throws IOException {
IndexWriter indexWriter = new IndexWriter(FSDirectory.open(new File(
indexPath)), new IndexWriterConfig(Version.LATEST,
new IKAnalyzer(true))); Document document = new Document(); document.add(new Field("id", "10", Field.Store.YES,
Field.Index.NOT_ANALYZED_NO_NORMS));
document.add(new Field("email", "9481629991", Field.Store.YES,
Field.Index.NOT_ANALYZED));
document.add(new Field("name", "小米", Field.Store.YES,
Field.Index.NOT_ANALYZED_NO_NORMS));
document.add(new Field("content", "小米好", Field.Store.NO,
Field.Index.ANALYZED)); // 这里的更新,从方法上能够看出,它实际上时将旧的删除,然后加入一个新文档的进去,将匹配到term的文档删除,然后就新的document加入进去
indexWriter.updateDocument(new Term("id", "1"), document); indexWriter.close();
}
}

另外附带高亮的项目代码

	/**
* 高亮的公共方法
* @param text --查询内容
* @param query --查询query
* @param field --查询域
* @return
*/
private String highligher(String text,Query query,String field) {
try {
QueryScorer scorer = new QueryScorer(query);
Fragmenter fragmenter = new SimpleSpanFragmenter(scorer);
Formatter formatter = new SimpleHTMLFormatter("<span class='lighter'>","</span>");
Highlighter lighter = new Highlighter(formatter,scorer);
lighter.setTextFragmenter(fragmenter);
String ht = lighter.getBestFragment(LuceneContext.getInstance().getAnalyzer(),
field,text);
if(ht==null) {
if(text.length()>=200) {
text = text.substring(0, 200);
text=text+"....";
}
return text;
}
else return ht.trim();
} catch (IOException e) {
e.printStackTrace();
} catch (InvalidTokenOffsetsException e) {
e.printStackTrace();
}
return text;
}

全文检索(二)-基于lucene4.10的增删改查的更多相关文章

  1. 基于pymysql模块的增删改查

    上课笔记 重点:(熟练)多表查询创建存储过程原生sql索引原理 pymysql 封装好的客户端cursor 底层就是一个send操作commit 告诉mysql真的要完成修改操作(不然修改不会生效)e ...

  2. EF6 学习笔记(二):操练 CRUD 增删改查

    EF6学习笔记总目录 ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 接上篇: EF6 学习笔记(一):Code First 方式生成数据库及初始化数据库实际操作 本篇原文链接: I ...

  3. 基于DRF的图书增删改查练习

    功能演示 信息展示 添加功能 编辑功能 删除功能 DRF构建后台数据 本例的Model如下 from django.db import models class Publish(models.Mode ...

  4. 基于DRF的图书增删改查

    功能演示 信息展示 添加功能 编辑功能 删除功能 DRF构建后台数据 本例的Model如下 from django.db import models class Publish(models.Mode ...

  5. Python Web实战:Python+Django+MySQL实现基于Web版的增删改查

    前言 本篇使用Python Web框架Django连接和操作MySQL数据库学生信息管理系统(SMS),主要包含对学生信息增删改查功能,旨在快速入门Python Web,少走弯路.效果演示在项目实战最 ...

  6. MySQL数据库(二)-数据库的增删改查

    简介: 以下是MySQL最基本的增删改查语句.在进行“增删改查”的操作之前,先建立一个包含数据表student的数据库,新建表grade(具体操作可以见上一篇). 一."增"-添加数据 1.1 为表中 ...

  7. MVC3学习:基于ObjectContext的数据增删改查操作

    数据库里面的表格,映射为对应的实体类.实体类的编写,可以自己手动编写,也可以使用工具或插件自动生成.在MVC3里面,我们可以使用VS的POCO插件自动生成实体类.如下图: 关于POCO插件的安装与使用 ...

  8. MongoDB(二)-- Java API 实现增删改查

    一.下载jar包 http://central.maven.org/maven2/org/mongodb/mongo-java-driver/ 二.代码实现 package com.xbq.mongo ...

  9. SQL学习(二)SQL基础的增删改查

    在测试时使用数据库时,用的比较多的就是增删改查SQL了. 一.增加(insert into ...values) 用于向表中插入新记录 1.不指定列(表示:依次插入所有列的值) insert into ...

随机推荐

  1. xshell全局设置配色方案

    新建XTerm1.xcs文件,将以下内容黏贴进去,保存退出 [XTerm] text=839496 cyan(bold)=93a1a1 text(bold)=408080 magenta=dd3682 ...

  2. 28. TRIGGERS ,29. USER_PRIVILEGES,30. VIEWS

    28. TRIGGERS TRIGGERS表提供有关触发器的信息.要查看有关表的触发器的信息,您必须具有该表的TRIGGER权限. TRIGGERS表有以下列: TRIGGER_CATALOG :触发 ...

  3. 让自己习惯C++

    条款1.C++是一个语言联邦 过程形式(procedural) 面向对象形式(object-oriented) 函数形式(function) 泛型形式(generic) 元编程形式(metaprogr ...

  4. hibernate中时间比较的小笔记

    // 开单时间 if (!"".equals(startDate) && startDate != null) { queryCondition = queryCo ...

  5. MySQL索引与Index Condition Pushdown(二)

    实验 先从一个简单的实验开始直观认识ICP的作用. 安装数据库 首先需要安装一个支持ICP的MariaDB或MySQL数据库.我使用的是MariaDB 5.5.34,如果是使用MySQL则需要5.6版 ...

  6. LINUX常见小问题汇总

    1. crontab的备份与恢复 备份crontab文件: crontab -l > $HOME/mycron 恢复丢失的crontab文件: 如果不小心误删了crontab文件,假设你在自己的 ...

  7. Java 关于循环的练习--和为n的正数序列

    要求:输入一个正数n,输出所有和为n的连续正数序列. 分析可以从1开始连续加,若到i的和等于n则输出1到i之间的连续正数,若到i的和大于n,则改为从2开始连续加,再判断到i的和是否等于n,等于则输出2 ...

  8. 用python写自定义模板

    模板语法有点像php !/usr/bin/env python """ #demo.py.html <html> <?py include head.p ...

  9. Mac 10.10 配置apache

    配置php 命令行工具:http://blog.csdn.net/evane1890/article/details/38759073 自从系统从OS X Mavericks 10.9升级到OS X  ...

  10. Leetcode 309.最佳买卖股票时机含冷冻期

    最佳买卖股票时机含冷冻期 给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格.​ 设计一个算法计算出最大利润.在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票): 你不 ...