搜索思路:
1 用一个indexSearcher对象,去一个预先建立的索引文件(indexFir)中查找关键字(key).
2其中要先对关键字采用特定的分词器(analyzer)进行解析(解析器(parser)),解析后作为query对象,再去查。
3.遍历结果集,根据docId去doc集合中找相应的doc.
4.设置高亮显示的格式,每条匹配记录显示的字符数。用highlighter对象,取得文章或数据的片段并将与关键字相同的文章,标红。
关于如何建立索引,请查看:搜索技术--建立索引(lucene3.0)
package com.jrj.datamart.action;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Fieldable;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.queryParser.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.Highlighter;
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.FSDirectory;
import org.apache.lucene.util.Version;
import com.jrj.datamart.model.ApiIndexEntity;
import com.jrj.datamart.model.Pagination;
//
//搜索并返回结果
public class SearcherAction extends BaseAction{
// 保存索引的地方
private String INDEX_DIR = "f:\\lucene\\luceneIndexDir";
private String keyword = "行情";
private int TOP_NUM = 100;
private int numIndexed;
// 保持搜索结果的List
List<ApiIndexEntity> apiIndexEntityLists = new ArrayList<ApiIndexEntity>();
// 搜索结果的个数
private int totalHitsNumber;
// 用时(毫秒)
private long spentTime;
//struts2中的主方法
public String execute() throws Exception {
System.out.println("execue of SearcherAction started...keyword: "
+ keyword);
long start = new Date().getTime();
File indexDir = new File(INDEX_DIR);
if (!indexDir.exists() || !indexDir.isDirectory()) {
throw new Exception(indexDir
+ " does not exist or is not a directory.");
}
search(indexDir, keyword);
long end = new Date().getTime();
spentTime = (end - start);
System.out.println("searing spent: " + spentTime + " milliseconds");
return "success";
}
//查詢
// @param indexDir
// 索引目录地址
// @param q
// 要查询的字符串
// @throws Exception
//
public void search(File indexDir, String q) throws Exception {
SmartChineseAnalyzer analyzer = new SmartChineseAnalyzer(
Version.LUCENE_30);
String field = "contents";
try {
// 排序
IndexSearcher indexSearch = new IndexSearcher(
FSDirectory.open(indexDir));
QueryParser parser = new QueryParser(Version.LUCENE_30, field,
analyzer);
// AND--->OR
parser.setDefaultOperator(QueryParser.OR_OPERATOR);
// 生成Query对象
// 多域查询
// String[] fields = { "icnname", "contents" };
// BooleanClause.Occur[] flags = { BooleanClause.Occur.SHOULD,
// BooleanClause.Occur.SHOULD };
// MultiFieldQueryParser.parse(Version.LUCENE_30, q, fields, flags,
// analyzer);
// TopScoreDocCollector topCollector = TopScoreDocCollector.create(
// indexSearch.maxDoc(), false);
Query query = parser.parse(q);
// 排序: 先API中文名,后描述
// SortField sortArray[];
// SortField sortField1 = new SortField("icnname", SortField.STRING,
// false);// false代表升序,TRUE代表降序
// SortField sortField2 = new SortField("contents",
// SortField.STRING,
// false);// false代表升序,TRUE代表降序
// sortArray = new SortField[] { sortField1, sortField2 };
// Sort sort = new Sort(sortArray);
// TopDocs topDocs = indexSearch.search(query, null, 1000, sort);
// indexSearch.search(query, topCollector);
TopDocs topDocs = indexSearch.search(query, TOP_NUM);
totalHitsNumber = topDocs.totalHits;
System.out.println("命中:" + totalHitsNumber);
// 输出结果
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
ApiIndexEntity apiIndexEntity;
// 将符合结果的都保持到list中。/
// 设置需要高亮的字段值
String[] highlightCol = { "icnname", "contents" };
Highlighter highlighter = null;
// 关键字高亮显示设置
// 设定高亮显示的格式,也就是对高亮显示的词组加上前缀后缀
SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter(
"<FONT COLOR='#FF0000'>", "</FONT>");
highlighter = new Highlighter(simpleHTMLFormatter, new QueryScorer(
query));
// 设置每次返回的字符数
highlighter.setTextFragmenter(new SimpleFragmenter(150));
for (int i = 0; i < topDocs.totalHits; i++) {
apiIndexEntity = new ApiIndexEntity();
Document targetDoc = indexSearch.doc(scoreDocs[i].doc);
for (Fieldable fa : targetDoc.getFields()) {
String value = targetDoc.get(fa.name());
for (String col : highlightCol) {
if (fa.name().equals(col)) {
// 设置高显内容
TokenStream tokenStream = analyzer.tokenStream(
"content", new StringReader(value));
value = highlighter.getBestFragment(tokenStream,
value);
if ("icnname".equals(fa.name())) {
apiIndexEntity.setIcnname(value == null ? targetDoc.get("icnname") : value);
} else if ("contents".equals(fa.name())) {
apiIndexEntity.setContents(value == null ? targetDoc.get("contents") : value);
}
}
}
}
apiIndexEntity.setApiid(Integer.parseInt(targetDoc.get("apiid")));
System.out.println("ApiId: "
+ targetDoc.get("apiid").toString());
System.out.println("API中文名: "
+ targetDoc.get("icnname").toString());
System.out
.println("内容:" + targetDoc.get("contents").toString());
apiIndexEntityLists.add(apiIndexEntity);
}
//将数据放入session中,
getSession().setAttribute("apiIndexEntityLists",apiIndexEntityLists);
//设置session时间1小时。
getSession().setMaxInactiveInterval(60*60);
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public int getNumIndexed() {
return numIndexed;
}
public void setNumIndexed(int numIndexed) {
this.numIndexed = numIndexed;
}
public String getINDEX_DIR() {
return INDEX_DIR;
}
public String getKeyword() {
return keyword;
}
public int getTOP_NUM() {
return TOP_NUM;
}
public void setINDEX_DIR(String iNDEX_DIR) {
INDEX_DIR = iNDEX_DIR;
}
public void setKeyword(String keyword) {
this.keyword = keyword;
}
public void setTOP_NUM(int tOP_NUM) {
TOP_NUM = tOP_NUM;
}
public List<ApiIndexEntity> getApiIndexEntityLists() {
return apiIndexEntityLists;
}
public void setApiIndexEntityLists(List<ApiIndexEntity> apiIndexEntityLists) {
this.apiIndexEntityLists = apiIndexEntityLists;
}
public int getTotalHitsNumber() {
return totalHitsNumber;
}
public void setTotalHitsNumber(int totalHitsNumber) {
this.totalHitsNumber = totalHitsNumber;
}
public long getSpentTime() {
return spentTime;
}
public void setSpentTime(int spentTime) {
this.spentTime = spentTime;
}
}
分享到:
相关推荐
4. 高亮显示:使用Highlighter类可以高亮显示搜索匹配的部分。 四、高级特性 1. 分块索引(Segment):Lucene以分块的形式存储索引,支持大数量的文档和高效的数据管理。 2. 基于内存的搜索:使用RAMDirectory...
Java Lucene 3.0的使用涉及到多个步骤,包括设置分析器(Analyzer)来处理不同语言的文本,创建索引(IndexWriter),查询索引(Searcher),以及对搜索结果进行评分和排序。同时,开发者还需要关注性能优化,例如...
通过《Lucene3.0原理与代码分析》的学习,读者可以掌握如何利用Lucene构建自己的全文搜索引擎,理解其高效检索背后的算法和技术,并能根据实际需求定制和优化索引和查询流程。尽管本文档基于3.0版本,但Lucene的基本...
除了搜索,Lucene还提供了一些其他功能,如文档的增删改查、多字段搜索、排序、分页、高亮显示搜索结果等。此外,它还可以与其他Apache项目如Solr和Elasticsearch集成,以构建更复杂的搜索引擎解决方案。 总之,...
5. 结果展示:处理搜索结果,包括排序、分页和高亮显示匹配的关键词。 三、部署到Tomcat等服务器 为了在Web环境中使用Lucene搜索器,我们需要将其部署到像Tomcat这样的Servlet容器中。首先,确保服务器环境中已经...
- **过滤器与高亮**:使用Filter可以对搜索结果进行进一步筛选,高亮工具可以突出显示匹配的搜索词。 **6. Lucene 3.0 版本特性** Lucene 3.0版本引入了一些重要的改进和新特性,包括: - 提升了性能和稳定性,...
- **Highlighting**:高亮显示搜索结果中的匹配部分。 - ** Spell Checking**:提供拼写纠错功能。 - **Multi-field search**:在一个文档中支持多字段搜索。 - **Update Index**:在线更新索引,无需重建整个...
- **高级特性探索**:深入探讨 Lucene 的一些高级特性,如高亮显示、近似匹配等。 #### 知识点四:Lucene 内部原理与定制化 除了基本的使用指南之外,《Lucene in Action》还深入剖析了 Lucene 的内部工作原理,为...
5. **内存缓存与过滤器**:Lucene提供`Filter`类来处理如文档过滤、高亮显示等功能。同时,`BitSet`类用于在内存中高效地存储和操作文档集。 6. **倒排索引的优化**:在`MergePolicy`和`MergeScheduler`中,你可以...
- **高亮显示**(Highlighting):在搜索结果中突出显示匹配的关键词。 - **分面搜索**(Faceted Search):提供分类和过滤功能,增强用户导航体验。 ### 6. 代码分析 在Lucene 3.0的代码中,你可以看到如何使用...
使用高亮器,我们可以突出显示搜索查询中的关键字,使其在文档内容中更加醒目。通常,这涉及到将原始文本分词,找到匹配的搜索词,然后用特定的格式(如不同的颜色或样式)替换这些关键词。在Lucene.Net 2.9.1中,这...
3. **高亮显示**: 可以突出显示搜索结果中的匹配词。 4. **近实时搜索**: 通过NRT(Near Real Time)机制,能在短时间内反映出索引的最新变化。 5. **复杂查询构造**: 提供高级查询构造器,如SpanQuery,支持精确...
`Highlighter`类则用于高亮显示搜索结果中的关键词。 7. **分布式搜索**:虽然3.0版本的Lucene不直接支持分布式搜索,但书中可能包含如何在单机环境下模拟多节点索引和查询的方法,这对于理解后来的Solr或Elastic...
在实际应用中,你可能需要根据业务需求对查询进行更复杂的配置,例如使用过滤器查询(filter queries)、高亮显示、分组、排序等。 对于提供的文件列表,`fileinfo.txt`可能包含关于文件元数据的信息,而其他`.txt`...