lucene全文检索概述(四)
目录
一.搜索索引的数据
lucene中提供丰富的查询功能,封装成查询对象Query的实例化类
比如词项查询,封装TermQuery,多域查询,封装MultiFieldQuery就可以实现搜索输入流从index索引中获取查询结果的功能;
1.入门词项查询(TermQuery)
词项查询:提供一个词语,如果这个词语对应域名,存在一个分词的词项,那么就将词项对应的document返回给查询;
1.步骤
- 指向一个索引所在的文件夹位置
- 生成一个利用输入流创建的查询对象searcher
- 包装一个Query对象根据功能封装实例
- 调用查询API查询出结果的封装集
- 遍历展示
2.代码模板
@Test
public void termQuery() throws Exception{
//1指向索引文件
Path path = Paths.get("d:/index01");
FSDirectory dir = FSDirectory.open(path);
//2 构造一个搜索对象,包装一个reader输入流
IndexReader reader=DirectoryReader.open(dir);
IndexSearcher search=new IndexSearcher(reader);
//3 构造词项查询条件TermQuery
//查询的对应域名称,和使用的词语,封装词项对象
Term term=new Term("name","三星");//content name
Query query=new TermQuery(term);
//4查询获取结果集,从结果集中获取document的id
TopDocs topDocs = search.search(query, 10);//results 从结果中查到最前的几条
//遍历获取id,通过id获取整整的数据对象document,观察每个document
//对不不同查询条件的评分是不一样的;
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
for (ScoreDoc scoreDoc : scoreDocs) {
//答应docuemnt的查询结果评分
System.out.println("评分:"+scoreDoc.score);
//从scoreDoc中获取document的id
int id = scoreDoc.doc;
//直接从数据中拿到document对象
Document doc = search.doc(id);//根据存储数据是的各种类型定义,能够拿到数据结果
System.out.println("title:"+doc.get("title"));
System.out.println("content:"+doc.get("content"));
System.out.println("publisher:"+doc.get("publisher"));
System.out.println("name:"+doc.get("name"));
System.out.println("price:"+doc.get("price"));
System.out.println("address:"+doc.get("address"));
System.out.println("image:"+doc.get("image"));
}
}
配合创建索引的数据封装进行,查询,如果要查询的数据不存在,无法获取到
3.运行测试
词项查询:利用分词的结果对比,有就查询,没有就空
4.总结:
提供一个词语,如果这个词语对应域名,存在一个分词的词项,那么就将词项对应的document返回给查询;是最基本的查询
2.多域查询
1.根据指定的多个域进行查询
将查询条件进行分词的拆分
例如,对content,name 查询"北京三星"
需要分词计算{北京}{三}{星}{三星},只要这些词项在2个域中存在任何一个,document就可以查到;
2.代码模板
定义多域的范围 content name
//封装多域查询条件 Query query
//定义多域的范围 content name
String[] fields={"content","name"};
//需要构造一个多域的解析器,解析查询字符串成为多个词项
Analyzer a=new IKAnalyzer6x();
MultiFieldQueryParser parser=new
MultiFieldQueryParser(fields,a);
Query query=parser.parse("北京三星");
//北京三星---{北京}{三}{星}{三星}
//构造了8个TermQuery content 北京 三星 星 三,name 北京 三星 三 星
//4查询获取结果集,从结果集中获取document的id
TopDocs topDocs = search.search(query, 10);//results 从结果中查到最前的几条
//遍历获取id,通过id获取整整的数据对象document,观察每个document
区别就是设置多域的范围
3.运行测试
为做测试,我在数据封装里,把第二条有关北京三星的信息全部删除,所以只会查询一条
4.总结:
多余查询,比普通查询的区别就是
多域 :一个多域的解析器,解析查询字符串成为多个词项,范围更加广阔,只要包含设置的域里的信息,全部获取到
3.布尔查询
1.lucene多种查询条件查询结果集
可以利用lucene多种查询条件查询结果集,
也可以利用布尔查询条件将多个其他的查询条件作为子条件完成多个子条件间的结果集关系输出
需要多个子条件的查询对象
2.代码模板
//需要多个子条件的查询对象
TermQuery query1=new TermQuery(new Term("content","北京"));
TermQuery query2=new TermQuery(new Term("name","三星"));
//利用boolean查询的子条件封装query1query2
BooleanClause bc1=new BooleanClause(query1,Occur.FILTER);//出现
BooleanClause bc2=new BooleanClause(query2,Occur.FILTER);
//Occur 的常量 MUST 包含 MUST_NOT 不包含 SHOULD 可以存在 类似并集 FILTER 无评分
//SHOULD如何MUST在同一个布尔条件中,不会起作用
//FILTER,MUST一个意思,但是结果中没有评分
Query query=new BooleanQuery.
Builder().add(bc1).add(bc2).build();
//构造一个布尔条件,俩个查询结果的交集
3.测试结果
无评分
4.总结
布尔查询,可以把其他查询融入进去,结果集就会显示的很丰富,
可以利用lucene多种查询条件查询结果集,也可以利用布尔查询条件将多个其他的查询条件作为子条件完成多个子条件间的结果集关系输出
4范围查询
1.指定查询域必须存在Point类型的特点
指定查询的域必须存在Point类型的特点,根据上限和下限值的设置可以查询对应数据的范围结果,从而获取document数据;
2.代码模板
只添加光标的那一行
3.运行测试
4.总结
就是按照给的范围查询到对应范围的数据
5.模糊查询
1.模糊查询对字符串模糊计算
对于英文人名查询,tramp,没有清晰的查询条件,可以利用模糊查询lucene对字符串有模糊计算,可以利用trump查到tramp tromp 等等
2.代码
FuzzyQuery query=new FuzzyQuery(new Term("content","%京"));
中文:曰,日,灵,炅 形象相像的字
3.测试结果
4.总结
就是简单的模糊查询
6通配符查询(?)
1.利用通配查询{X?}代替后面字符串
有时候需要从词项中,找到对应通配的逻辑,{三星},{三天},{三个}
可以利用通配查询{三?}代替后面字符串
2.代码模板
WildcardQuery query=new WildcardQuery(new Term("name","三?"))
3.测试结果
4.总结
就是简单的通配查询{三?}代替后面字符串
lucene总结:
- lucene作为工具包,提供各种全文检索技术需要的内容,直接极大的降低了开发人员开发全文检索技术的成本.
- 原生态java语言开发,导致其他语言使用的开发人员无法直接使用.ELASTICSAERCH SOLR这种技术的出现解决了其他语言调用全文检索及的屏障的问题;
- 开发一个技术,完成对外的访问,对内的lucene封装,对外访问使用公用的协议,让其他语言直接调用协议的接口访问我的技术,直接可以使用内部封装的lucene代码;web应用的封装对外提供http接口协议(一次请求,一次响应)