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编程步骤

1)    创建和配置高亮器

一个高亮器的创建需要两个条件:

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查询索引库、分页、过滤、排序、高亮的更多相关文章

  1. Lucene查询索引(分页)

    分页查询只需传入每页显示记录数和当前页就可以实现分页查询功能 Lucene分页查询是对搜索返回的结果进行分页,而不是对搜索结果的总数量进行分页,因此我们搜索的时候都是返回前n条记录 package c ...

  2. (转) 淘淘商城系列——使用SolrJ查询索引库

    http://blog.csdn.net/yerenyuan_pku/article/details/72908538 我们有必要在工程中写查询索引库的代码前先进行必要的测试.我们先到Solr服务页面 ...

  3. lucene内存索引库、分词器

    内存索引库 特点 在内存中开辟一块空间,专门为索引库存放.这样有以下几个特征: 1)    因为索引库在内存中,所以访问速度更快. 2)    在程序退出时,索引库中的文件也相应的消失了. 3)    ...

  4. Lucene 07 - 对Lucene的索引库进行增删改查

    目录 1 添加索引 2 删除索引 2.1 根据Term删除索引 2.2 删除全部索引(慎用) 3 更新索引 数据保存在关系型数据库中, 需要实现增.删.改.查操作; 索引保存在索引库中, 也需要实现增 ...

  5. Lucene之索引库的维护:添加,删除,修改

    索引添加 Field域属性分类 添加文档的时候,我们文档当中包含多个域,那么域的类型是我们自定义的,上个案例使用的TextField域,那么这个域他会自动分词,然后存储 我们要根据数据类型和数据的用途 ...

  6. 搜索引擎学习(三)Lucene查询索引

    一.查询理论 创建查询:构建一个包含了文档域和语汇单元的文档查询对象.(例:fileName:lucene) 查询过程:根据查询对象的条件,在索引中找出相应的term,然后根据term找到对应的文档i ...

  7. Lucene查询索引

    索引创建 以新闻文档为例,每条新闻是一个document,新闻有news_id.news_title.news_source.news_url.news_abstract.news_keywords这 ...

  8. lucene查询索引之QueryParser解析查询——(八)

    0.语法介绍:

  9. lucene查询索引之Query子类查询——(七)

    0.文档名字:(根据名字索引查询文档)

随机推荐

  1. 【前端】Ubuntu16下nodejs+npm+vue环境配置

    笔者最近在学习vue.js,不过一直都是在runoob上面各种尝试.今天笔者在本机(Ubuntu16.04)尝试部署了nodejs+npm+vue开发环境,接下来将尽可能详细的讲述安装过程,帮助新人少 ...

  2. 是否有必要学习使用纯Verilog写一个SDRAM控制器

    在做这个SDRAM控制器之前,博主有一个疑问,对于学生来说,是否有必要学习用纯Verilog写一个SDRAM控制器?因为目前X家和A家都有了DDR IP Core,对于要实现一个应用可以直接调用IP ...

  3. [SHOI2011]双倍回文

    Description   Input 输入分为两行,第一行为一个整数,表示字符串的长度,第二行有个连续的小写的英文字符,表示字符串的内容. Output 输出文件只有一行,即:输入数据中字符串的最长 ...

  4. 洛谷P1397 [NOI2013]矩阵游戏

    矩阵快速幂+费马小定理 矩阵也是可以跑费马小定理的,但是要注意这个: (图是盗来的QAQ) 就是说如果矩阵a[i][i]都是相等的,那么就是mod p 而不是mod p-1了 #include< ...

  5. [bzoj4883][Lydsy2017年5月月赛]棋盘上的守卫

    来自FallDream的博客,未经允许,请勿转载, 谢谢. 在一个n*m的棋盘上要放置若干个守卫.对于n行来说,每行必须恰好放置一个横向守卫:同理对于m列来说,每列 必须恰好放置一个纵向守卫.每个位置 ...

  6. 关于InnoDB的读写锁类型以及加锁方式

    (本文为了方便,英文关键词都都采用小写方式,相关知识点会简单介绍,争取做到可以独立阅读) 文章开始我会先介绍本文需要的知识点如下: innodb的聚簇索引(聚集索引)和非聚簇索引(二级索引.非聚集索引 ...

  7. face-alignment:用 pytorch 实现的 2D 和 3D 人脸对齐库

    使用世界上最准确的面对齐网络从 Python 检测面部地标,能够在2D和3D坐标中检测点. 项目地址:https://github.com/1adrianb/face-alignment 作者: 阿德 ...

  8. 【精解】EOS智能合约演练

    EOS,智能合约,abi,wasm,cleos,eosiocpp,开发调试,钱包,账户,签名权限 热身 本文旨在针对EOS智能合约进行一个完整的实操演练,过程中深入熟悉掌握整个EOS智能合约的流程,过 ...

  9. 在java中String类为什么要设计成final

    在java中String类为什么要设计成final? - 胖胖的回答 - 知乎 https://www.zhihu.com/question/31345592/answer/114126087

  10. Mysql锁机制--索引失效导致行锁变表锁

    Mysql 系列文章主页 =============== Tips:在阅读本文前,最好先阅读 这篇(Mysql锁机制--行锁)文章~ 在上篇文章中,我们看到InnoDB默认的行锁可以使得操作不同行时不 ...