lucene查询索引库、分页、过滤、排序、高亮
2.查询索引库
插入测试数据 xx.xx. index. ArticleIndex
@Test
public
void testCreateIndexBatch() throws Exception{
IndexWriter indexWriter = new IndexWriter(LuceneUtils.directory,
LuceneUtils.analyzer,MaxFieldLength.LIMITED);
for(inti=0;i<25;i++){
Article article = new Article();
article.setId(1L+i);
article.setTitle("lucene可以做搜索引擎");
article.setContent("baidu,google都是很好的搜索引擎");
indexWriter.addDocument(DocumentUtils.article2Document(article));
}
indexWriter.close();
}
2.1查询
2.1.1分页
xx.xx.xx.index.ArticleIndex下
/**
*
* @param firstResult
* 当前页的第一行在集合中的位置
* @param maxResult
* 每页显示的最大的行数
* @throws Exception
*/
public
void testSearchIndexDispage(int firstResult,int maxResult)throws
Exception{
IndexSearcher indexSearcher = new IndexSearcher(LuceneUtils.directory);
QueryParser queryParser = new MultiFieldQueryParser(Version.LUCENE_30,new String[]{"title","content"},
LuceneUtils.analyzer);
Query query = queryParser.parse("lucene");
TopDocs topDocs =indexSearcher.search(query,25);
int count = Math.min(topDocs.totalHits,firstResult+maxResult);
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
List<Article> articleList = new ArrayList<Article>();
for(inti=firstResult;i<count;i++){
Document document = indexSearcher.doc(scoreDocs[i].doc);
Article article =DocumentUtils.document2Article(document);
articleList.add(article);
}
for(Article article:articleList){
System.out.println(article.getId());
System.out.println(article.getTitle());
System.out.println(article.getContent());
}
}
@Test
public
void testDispage() throws Exception{
this.testSearchIndexDispage(10, 10);
}
说明:
1) 在全文检索系统中,一般查询出来的内容比较多,所以必须将查询出来的内容进行分页处理。
2) 原理同hibernate的分页查询。在hibernate的分页查询中,有两个参数:
int firstResult 当前页的第一行在数据库里的行数
int maxResult 每页显示的页数
2.1.2搜索方式
/**
* 1、关键词查询
* 2、查询所有文档
* 3、范围查询
* 4、通配符查询
* 5、短语查询
* 6、Boolean查询
* @author Administrator
*
*/
public class QueryTest {
/**
* 关键词查询
* 因为没有分词器,所以区分大小写
*/
@Test
public void testTermQuery() throws Exception{
Term term = new Term("title","lucene");
Query query = new TermQuery(term);
this.showData(query);
}
/**
* 查询所有的文档
*/
@Test
public void testAllDocQuery() throws Exception{
Query query = new MatchAllDocsQuery();
this.showData(query);
}
/**
* 通配符查询
* * 代表任意多个任意字符
* ? 任意一个任意字符
*/
@Test
public void testWildCartQuery() throws Exception{
Term term = new Term("title","*.java");
Query query = new WildcardQuery(term);
this.showData(query);
}
/**
* 短语查询
* 所有的关键词对象必须针对同一个属性
* @param query
* @throws Exception
*/
@Test
public void testPharseQuery() throws Exception{
Term term = new Term("title","lucene");
Term term2 = new Term("title","搜索");
PhraseQuery query = new PhraseQuery();
query.add(term,0); //0代表第0个位置
query.add(term2,4);
this.showData(query);
}
/**
* boolean查询
* 各种关键词的组合
* @param query
* @throws Exception
*/
@Test
public void testBooleanQuery() throws Exception{
Term term = new Term("title","北京");
TermQuery termQuery = new TermQuery(term);
Term term2 = new Term("title","美女");
TermQuery termQuery2 = new TermQuery(term2);
Term term3 = new Term("title","北京美女");
TermQuery termQuery3 = new TermQuery(term3);
BooleanQuery query = new BooleanQuery();
query.add(termQuery,Occur.SHOULD);
query.add(termQuery2,Occur.SHOULD);
query.add(termQuery3,Occur.SHOULD);
this.showData(query);
}
/**
* 范围查询
* @param query
* @throws Exception
*/
@Test
public void testRangeQuery() throws Exception{
Query query = NumericRangeQuery.newLongRange("id", 5L, 10L, true, true);
this.showData(query);
}
private void showData(Query query) throws Exception{
IndexSearcher indexSearcher = new IndexSearcher(LuceneUtils.directory);
TopDocs topDocs = indexSearcher.search(query, 25);
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
List<Article> articleList = new ArrayList<Article>();
for(ScoreDoc scoreDoc:scoreDocs){
Document document = indexSearcher.doc(scoreDoc.doc);
Article article = DocumentUtils.document2Article(document);
articleList.add(article);
}
for(Article article:articleList){
System.out.println(article.getId());
System.out.println(article.getTitle());
System.out.println(article.getContent());
}
}
}
1) 使用查询字符串
QueryParser->Query对象
可以使用查询条件
“lucene AND 互联网” 都出现符合查询条件
“lucene OR 互联网” 只要出现其一就符合查询条件
2) 自己创建与配置Query对象
i. 关键词查询(TermQuery)
注:因为保存引索的时候是通过分词器保存,所以所有的因为在索引
库里都为小写,所以lucene必须得小写,不然查询不到。如果使用
查询字符串进行查询,对应的语法格式为:title:lucene
ii. 查询所有文档
如果使用查询字符串,对应语法:*:*
iii. 范围查询
注:在lucene中,处理数字是不能直接写入的,要进行转化。NumberStringTools帮助类给出了转化工具:
在工具类DocumentUtils中也做相应的转化:
Field idField = new Field("id",NumericUtils.longToPrefixCoded(article.getId()),
Store.YES,Index.NOT_ANALYZED);
article.setId(NumericUtils.prefixCodedToLong(document.get("id")));
iv. 通配符查询
v. 短语查询
vi. Boolean查询
可以把多个查询条件组合成一个查询条件
注意:
1、 单独使用MUST_NOT 没有意义
2、 MUST_NOT和MUST_NOT 无意义,检索无结果
3、单独使用SHOULD:结果相当于MUST
4、SHOULD和MUST_NOT: 此时SHOULD相当于MUST,结果同MUST和MUST_NOT
5、MUST和SHOULD:此时SHOULD无意义,结果为MUST子句的检索结果
2.3排序
2.3.1相关度得分
实验一:
在索引库中内容完全相同的情况下,用几个关键词搜索,看是否得分相同。
结果:
同一个关键词得分对于所有的Document是一样的。但是不同的关键词的分数不一样。关键词和文本内容匹配越多,得分越高。也就是相关度得分就高
实验二:
再插入一个Document,在其中的content中增加一个关键词,然后保存到索引库中。
结果:
同一个关键词如果在所有匹配的文本中的相关度得分不一样,按照相关度得分从高到低的顺序排列。
实验三:
如果想从百度上排名第一,就得控制相关度得分。在lucene中,可以人为控制相关度得分。
利用Document.setBoost可以控制得分。默认值为1
结论:
利用Document.setBoost可以人为控制相关度得分,从而把某一个引索内容排到最前面。
public class SortTest {
/**
* 1、相同的结构,相同的关键词,得分一样
* 2、相同的结构,不同的关键词,得分不一样,一般来说中文比较高
* 3、不同的结构,关键词出现的次数越多,得分越高
* 4、利用document.setBoost(100)可以人为的提高相关度得分
* @throws Exception
*/
@Test
public void testSearchIndex() throws Exception{
IndexSearcher indexSearcher = new IndexSearcher(LuceneUtils.directory);
QueryParser queryParser = new MultiFieldQueryParser(Version.LUCENE_30, new String[]{"title","content"}, LuceneUtils.analyzer);
Query query = queryParser.parse("lucene");
TopDocs topDocs = indexSearcher.search(query, 26);
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
List<Article> articleList = new ArrayList<Article>();
for(ScoreDoc scoreDoc:scoreDocs){
float score = scoreDoc.score;
System.out.println(score);//相关的得分
Document document = indexSearcher.doc(scoreDoc.doc);
Article article = DocumentUtils.document2Article(document);
articleList.add(article);
}
for(Article article:articleList){
System.out.println(article.getId());
System.out.println(article.getTitle());
System.out.println(article.getContent());
}
}
}
2.4高亮
用户在百度的首界面输入要搜索的关键字,比如:林志玲,看出林志玲这个关键词变成了红色,这就是高亮。
2.4.1高亮的作用
1) 使关键字的颜色和其他字的颜色不一样,这样关键字就比较突出。
方法:在关键字周围加上前缀和后缀
<font color=’red’>林志玲</font>
2) 生成摘要(从关键词出现最多的地方截取一段文本),可以配置要截取文本的字符数量。
2.4.2编程步骤
一个高亮器的创建需要两个条件:
Formatter 要把关键词显示成什么样子
Scorer 查询条件
Fragmenter设置文本的长度。默认为100。
如果文本的内容长度超过所设定的大小,超过的部分将显示不出来。
2) 使用高亮器
getBestFragment为得到高亮后的文本。
参数:
i. 分词器。
如果是英文:StandardAnalyzer
如果是中文:IKAnalyzer
ii. 在哪个属性上进行高亮
iii. 要高亮的内容
/**
* 高亮
* * 使关键字变色
* * 设置
* * 使用
* * 控制摘要的大小
* @author Administrator
*/
public class HighlighterTest {
@Test
public void testSearchIndex() throws Exception{
IndexSearcher indexSearcher = new IndexSearcher(LuceneUtils.directory);
QueryParser queryParser = new MultiFieldQueryParser(Version.LUCENE_30, new String[]{"title","content"}, LuceneUtils.analyzer);
Query query = queryParser.parse("Lucene");
TopDocs topDocs = indexSearcher.search(query, 25);
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
/***********************************************************************/
//创建和配置高亮器
/**
* 给关键字加上前缀和后缀
*/
Formatter formatter = new SimpleHTMLFormatter("<font color='red'>","</font>");
/**
* scorer封装了关键字
*/
Scorer scorer = new QueryScorer(query);
Highlighter highlighter = new Highlighter(formatter,scorer);
/**
* 创建一个摘要
*/
Fragmenter fragmenter = new SimpleFragmenter(10);
highlighter.setTextFragmenter(fragmenter);
/***********************************************************************/
List<Article> articleList = new ArrayList<Article>();
for(ScoreDoc scoreDoc:scoreDocs){
float score = scoreDoc.score;
System.out.println(score);//相关的得分
Document document = indexSearcher.doc(scoreDoc.doc);
Article article = DocumentUtils.document2Article(document);
/*
* 使用高亮器
*/
/**
* 1、分词器
* 查找关键词
* 2、字段
* 在哪个字段上进行高亮
* 3、字段的内容
* 把字段的内容提取出来
*/
String titleText = highlighter.getBestFragment(LuceneUtils.analyzer, "title", document.get("title"));
String contentText = highlighter.getBestFragment(LuceneUtils.analyzer, "content", document.get("content"));
if(titleText!=null){
article.setTitle(titleText);
}
if(contentText!=null){
article.setContent(contentText);
}
articleList.add(article);
}
for(Article article:articleList){
System.out.println(article.getId());
System.out.println(article.getTitle());
System.out.println(article.getContent());
}
}
}
lucene查询索引库、分页、过滤、排序、高亮的更多相关文章
- Lucene查询索引(分页)
分页查询只需传入每页显示记录数和当前页就可以实现分页查询功能 Lucene分页查询是对搜索返回的结果进行分页,而不是对搜索结果的总数量进行分页,因此我们搜索的时候都是返回前n条记录 package c ...
- (转) 淘淘商城系列——使用SolrJ查询索引库
http://blog.csdn.net/yerenyuan_pku/article/details/72908538 我们有必要在工程中写查询索引库的代码前先进行必要的测试.我们先到Solr服务页面 ...
- lucene内存索引库、分词器
内存索引库 特点 在内存中开辟一块空间,专门为索引库存放.这样有以下几个特征: 1) 因为索引库在内存中,所以访问速度更快. 2) 在程序退出时,索引库中的文件也相应的消失了. 3) ...
- Lucene 07 - 对Lucene的索引库进行增删改查
目录 1 添加索引 2 删除索引 2.1 根据Term删除索引 2.2 删除全部索引(慎用) 3 更新索引 数据保存在关系型数据库中, 需要实现增.删.改.查操作; 索引保存在索引库中, 也需要实现增 ...
- Lucene之索引库的维护:添加,删除,修改
索引添加 Field域属性分类 添加文档的时候,我们文档当中包含多个域,那么域的类型是我们自定义的,上个案例使用的TextField域,那么这个域他会自动分词,然后存储 我们要根据数据类型和数据的用途 ...
- 搜索引擎学习(三)Lucene查询索引
一.查询理论 创建查询:构建一个包含了文档域和语汇单元的文档查询对象.(例:fileName:lucene) 查询过程:根据查询对象的条件,在索引中找出相应的term,然后根据term找到对应的文档i ...
- Lucene查询索引
索引创建 以新闻文档为例,每条新闻是一个document,新闻有news_id.news_title.news_source.news_url.news_abstract.news_keywords这 ...
- lucene查询索引之QueryParser解析查询——(八)
0.语法介绍:
- lucene查询索引之Query子类查询——(七)
0.文档名字:(根据名字索引查询文档)
随机推荐
- 【Swift】swift定义全局变量
swift定义全局变量非常简单哈,只要在类class上面直接定义,就是全局变量了 当需要在类里面定义一个类函数访问的变量的时候,直接在var或者let 前面加一个 static
- 小白学习java设计模式之策略模式
策略模式:1.分析项目中的变化部分与不变部分(每个设计模式都要分析的)2.多用组合少用继承;用行为类组合,而不是行为继承,更具有弹性直接上代码: package com.wz.oneStrategis ...
- [Codeforces 100633J]Ceizenpok’s formula
Description 题库链接 求 \[C_n^m \mod p\] \(1\leq m\leq n\leq 10^{18},2\leq p\leq 1000000\) Solution 一般的 \ ...
- [HNOI2015]落忆枫音
题目描述 「恒逸,你相信灵魂的存在吗?」 郭恒逸和姚枫茜漫步在枫音乡的街道上.望着漫天飞舞的红枫,枫茜突然问出这样一个问题. 「相信吧.不然我们是什么,一团肉吗?要不是有灵魂......我们也不可能再 ...
- [BZOJ1977]严格次小生成树
[问题描述] 小C最近学了很多最小生成树的算法,Prim算法.Kurskal算法.消圈算法等等. 正当小C洋洋得意之时,小P又来泼小C冷水了.小P说,让小C求出一个无向图的次小生成树,而且这个次小生成 ...
- CodeForces - 724G:Xor-matic Number of the Graph
两点之间的任意路径都可表示为 随便某一条路径xor任何多个环, 然后可以用线性基来做,这样不会重复的, 另外必须一位一位的处理,xor是不满足结合律的 #include<cstdio> ...
- Codeforces278E Tourists
来自FallDream的博客,未经允许,请勿转载,谢谢. 给定一张无向图,有点权,要支持单点修改点权和询问从一个点到另一个点不重复经过节点的路径上点权最小值的最小值. n,m<=10^5 考虑求 ...
- [bzoj4893]项链分赃
来自FallDream的博客,未经允许,请勿转载,谢谢. 有一串长度为n(n<=10^5)的项链,上面有红绿蓝三种颜色的珠子,每种颜色的珠子数目都是偶数,现在要你把它切几刀分成若干段,把其中一些 ...
- Windows提示dll组件丢失
我们在运行一些软件时,常常会遇到这种问题.下面就来提供解决办法: 登陆网址:www.dll-files.com. 找到页面的搜索部分,并且进行相关搜索: 下图显示了相关的dll下载链接. 下载解压即可 ...
- 设置思科设备console密码、enable密码、vty登录密码
思科设备各级密码:1) console密码 SW2(config)#line console 0SW2(config-line)#password ciscoSW2(config-line)#log ...