个人笔记之用,如有错误,恳请批评指正。
高亮,多字段查询,分页查询。
|
分页查询,接上
若查询第二页,每页5条。查询10条。遍历取回6-10条。需判断总条数与需要条数的关系
//总记录数小于end,说明scoreDocs不满end条。即返回的是start--totalHits条。否则返回的是start--end条
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
int size = end;
if(topDocs.totalHits<end) {
size = topDocs.totalHits;
}
|
|
IndexWriterUtil的编写:整个项目唯一一个IndexWriter,并且在虚拟机关闭时自动close();
//注册虚拟机关闭线程
Runtime.getRuntime().addShutdownHook(new Thread(){
@Override
public void run() {
try {
indexWriter.close();
System.out.println("indexWriter已经关闭了!");
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
|
|
做系统不仅要考虑功能,还要考虑非功能的东西,比如说性能,可维护性,交互性等。
|
|
IKAnalyzer中文分词器:开源的,轻量级的分词器。
使用IKAnalyzer,当参数为true时,表示使用最大词长分词,false表示使用细粒度分词
步骤:
1、 导包
2、 配置文件IKAnalyzer.cfg.xml到src目录下
3、 禁用词汇ext_stopword.dic和自定义词汇mydict.dic放到src目录下(/)(格式:第一行空格换行,并注意保存的编码要一致)
禁用词汇不建立索引库,所以搜索不到。但是会存储进索引库。
4、 //使用IKAnalyzer,当参数为true时,表示使用最大词长分词,false表示使用细粒度分词
IKAnalyzer = new IKAnalyzer(true);
IndexWriter indexWriter = new IndexWriter(LuceneUtil.getDirectory(), LuceneUtil.getAnalyzer(), LuceneUtil.getMaxFieldLength());
注意:当indexWriter用了IKAnalyzer以后,indexSearcher也要用IKAnalyzer
|
排序和多字段查询
|
//创建排序字段,参数一:指定排序字段;参数二:字段类型;参数三:设置升序或子降序,true为降序
SortField goodsId = new SortField("goodsId",SortField.INT,true);
Sort sort=new Sort();
//设置排序字段(可以多个字段)到sort对象中,排序的优先级,前者优先于后者
sort.setSort(goodsId,其它SortField对象);
//使用IKQueryParser进行多字段数据查询
Query query=IKQueryParser.parseMultiField(new String[]{"goodsName","goodsRemark"},keyword);
//执行查询,使用search(Query query , Filter filter , int n , Sort sort)方法,返回20条记录,加入排序设置信息
TopDocs topDocs = indexSearcher.search(query, null,20,sort);//null过滤器
|
|
排序:
new SortField(“指定排序字段”,“字段类型”,“true:升序 false:降序”);
sort = new sort();
sort.setSort(多个sortField);
多字段:
query = IKQueryParser.parseMultiField(new String[]{“字段名”},“keyword”);
查询:
indexSearcher.search(query,null,20,sort);
//排序+多字段查询
public void searchBySortAndMultiField(String keyword){
try {
IndexSearcher indexSearcher = IndexSearcherUtil.getIndexSearcher();
//设置排序
SortField idField = new SortField("id", SortField.INT, false);
//SortField contentField = new SortField("content",SortField.STRING,false);
Sort sort = new Sort();
sort.setSort(idField);
//设置多字段查询
Query query = IKQueryParser.parseMultiField(new String[]{"title","content"}, keyword);
TopFieldDocs topFieldDocs = indexSearcher.search(query, null, 20, sort);
System.out.println("总匹配数:"+topFieldDocs.totalHits);
ScoreDoc[] scoreDocs = topFieldDocs.scoreDocs;
for (ScoreDoc scoreDoc : scoreDocs) {
Document doc = indexSearcher.doc(scoreDoc.doc);
System.out.println("title:"+doc.get("title")+"content:"+doc.get("content"));
}
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
|
|
高亮:
|
获取到Document对象后,对doc中指定字段的指定内容利用HighLighter对象进行高亮返回带有高亮格式的指定字段值,重新setValue到document中的对应field中,封装到对象输出。
具体步骤:
Document doc = indexSearcher.doc(scoreDocs[i].doc);
//设置高亮格式
Formatter fomatter = new SimpleHTMLFormatter("<font color='red'>", "</font>");
//设置需要高亮的关键字,指定查询信息
Scorer scorer = new QueryScorer(query);
Highlighter highlighter = new Highlighter(fomatter,scorer);
//制定高亮后的长度,需要SimpleFragmenter类型参数,指定20
int length = 20;
highlighter.setTextFragmenter(new SimpleFragmenter(length));
//设置对哪些字段进行高亮,返回高亮后的结果
String titleResult = highlighter.getBestFragment(LuceneUtil.getIKAnalyzer(), "title", doc.get("title"));
String contentResult = highlighter.getBestFragment(LuceneUtil.getIKAnalyzer(), "content", doc.get("content"));
|
|
对返回的String判空:
Document doc = indexSearcher.doc(scoreDocs[i].doc);
//设置高亮格式
Formatter fomatter = new SimpleHTMLFormatter("<font color='red'>", "</font>");
//设置需要高亮的关键字,指定查询信息
Scorer scorer = new QueryScorer(query);
Highlighter highlighter = new Highlighter(fomatter,scorer);
//制定高亮后的长度,需要SimpleFragmenter类型参数,指定20
int length = 20;
highlighter.setTextFragmenter(new SimpleFragmenter(length));
//设置对哪些字段进行高亮,返回高亮后的结果
String titleResult = highlighter.getBestFragment(LuceneUtil.getIKAnalyzer(), "title", doc.get("title"));
String contentResult = highlighter.getBestFragment(LuceneUtil.getIKAnalyzer(), "content", doc.get("content"));
对HighLighterUtils的抽取
Document doc = indexSearcher.doc(scoreDocs[i].doc);
//设置高亮格式
Formatter fomatter = new SimpleHTMLFormatter("<font color='red'>", "</font>");
//设置需要高亮的关键字,指定查询信息
Scorer scorer = new QueryScorer(query);
Highlighter highlighter = new Highlighter(fomatter,scorer);
//制定高亮后的长度,需要SimpleFragmenter类型参数,指定20
int length = 20;
highlighter.setTextFragmenter(new SimpleFragmenter(length));
//设置对哪些字段进行高亮,返回高亮后的结果
String titleResult = highlighter.getBestFragment(LuceneUtil.getIKAnalyzer(), "title", doc.get("title"));
String contentResult = highlighter.getBestFragment(LuceneUtil.getIKAnalyzer(), "content", doc.get("content"));
|
索引库优化
|
indexWriter.optimize()方法使用
新增数据时在提交前使用optimize()方法: 将把产生.cfs的文档和原来的文档压缩并合并为一个
修改操作类的保存数据方法
indexWriter.optimize();
indexWriter.setMergeFactor()方法使用
关键代码:
//通过设置合并因子合并文件,如下:产生三个cfs文档(包括合并的)将压缩合并成一个
indexWriter.setMergeFactor(3);
|
写在最后,lucene初步入门,能实现初步的增删改查,分段、排序、高亮以及索引优化。
增删改查
Term 对应索引表里的关键词及字段 newTerm(“字段名”,”字段值”)
TopDocs只包括总记录数和文档编号(scoreDoc.doc)
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
Document document = indexSearcher.doc(scoreDoc.doc);
通过文档编号再次查询searcher.doc(scoreDoc.doc)返回document
update原则:根据字段的值进行修改数据内容,先删除再添加。如果字段值不存在,则新增一条记录(文档),如果字段值唯一,那就相当于根据主键修改数据;如果字段值对应多条记录(文档),则其他记录(文档)将被逻辑删除后,再添加一条记录(文档)。
Delete原则:根据传入的字段值搜索对应的记录(文档),进行删除。
使用细节:
尽量减少不必要的字段的存储。Store.YES/Store.NO
不需要检索的内容尽量不要建立索引。Index.ANALYZED/Index.NOT_ANALYZED/Index.NO
非文本格式需要提前转化为字符串。
需要整体存放的内容不要分词,例如:ID、价格、专业词。Index.NOT_ANALYZED