您的位置:首页 > 其它

lucene查询索引库、分页、过滤、排序、高亮

2014-07-04 14:39 936 查看

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());
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐