Lucene查询出来的数据排序有两个方面会影响到,
一是tf(Term frequency), 查询的关键字在当前文档中出现 的次数越多,权重越高,排名越靠前
二是df(Document frequency),查询的关键字在多个文档中出现的资料越多,权重相对较低。
那么查询出来的数据是否可以人为影响排序呢? 答案是可以的,总共有两种方式。
一是在创建索引时,设置boost参数:
/**
* 创建索引时,对指定数据设置影响排序的参数
* @创建时间:2017年10月8日16:17:21
*/
@Test
public void zfIndex() throws IOException{
//创建写入流,并指定分词器、索引目录
Directory directory = FSDirectory.open(new File("D:"+File.separator+"lucene_index"+File.separator));
IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_4_10_3, new StandardAnalyzer());
IndexWriter writer = new IndexWriter(directory, config);
//从数据库获取数据
BookDao dao = new BookDaoImpl();
List<Book> books = dao.queryBooks();
//创建集合中,用以保存要存储到索引文档中的内容
List<Document> documents = new ArrayList<>();
Document document ;
for(Book book : books){
document = new Document();
//创建索引域及相关内容
Field id = new StringField("id", book.getId().toString(), Store.YES);
Field name = new TextField("name", book.getName(), Store.YES);
Field price = new FloatField("price", book.getPrice(), Store.YES);
Field pic = new StringField("pric", book.getPic(), Store.YES);
Field description = new TextField("description", book.getDescription(),Store.YES);
//设置boost参数,会影响到它的排序,但注意,在TextField上可以设置boost,StringField、StoreField上不能设置
if(book.getId() == 5){
description.setBoost(100f);
}
//创建一个document文档内容
document.add(id);
document.add(name);
document.add(price);
document.add(pic);
document.add(description);
//将当前文档内容写入到集合中
documents.add(document);
}
//将集合中的数据写入索引文件
for(Document doc : documents){
writer.addDocument(doc);
}
//关闭流
writer.close();
}
第二种是在查询时设置参数,只在MultiFieldQueryParser 对象中生效
/**
* 查询lucene索引数据 @创建时间:2017年10月7日22:57:00
*/
public void query(Query query) {
try {
// 指定查询的索引目录
Directory directory = FSDirectory.open(new File("D:" + File.separator + "lucene_index" + File.separator));
// 创建流对象
IndexReader reader = DirectoryReader.open(directory);
// 通过流对象创建索引搜索对象
IndexSearcher searcher = new IndexSearcher(reader);
// 将查询到的指定索引域数据赋值给TopDocs
TopDocs topDocs = searcher.search(query, 10);
// 根据获取查询到的总数据
int totalHits = topDocs.totalHits;
// 输出
System.out.println("共查询到数据总数为:" + totalHits);
System.out.println();
// 将查询到的索引数据赋值给数组
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
// 如果未查询到数据,则输出提示
if (scoreDocs == null || scoreDocs.length == 0) {
System.out.println("未查询到数据");
} else {
// 如果查询到的有数据。则循环输出
for (ScoreDoc doc : scoreDocs) {
// 获取索引ID
int docID = doc.doc;
// 根据索引数据查询文档中对应的数据
Document document = searcher.doc(docID);
// 将查询到的数据输出
System.out.println("ID:" + document.get("id"));
System.out.println("name:" + document.get("name"));
System.out.println("price:" + document.get("price"));
System.out.println("pic:" + document.get("pic"));
System.out.println("description:" + document.get("description"));
System.out.println("==================================");
System.out.println();
System.out.println();
}
}
// 关闭流
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 要查询时,使用Map<String, Float> boosts 设置查询结
* 果的排序
* 只有在MultiFieldQueryParser 中才可以使用
* @创建时间:2017年10月8日16:27:42
*/
@Test
public void testSeracher() throws ParseException{
//查询的多个索引域名称
String[] fields = {"name","description"};
//分词器
Analyzer analyzer = new StandardAnalyzer();
//以下设置的效果:当搜索的关键字在name存在时,会优先将name包含关键字的内容排序在最前面
Map<String, Float> boosts = new HashMap<String,Float>();
boosts.put("name", 200f);
//多域查询对象
MultiFieldQueryParser parser= new MultiFieldQueryParser(fields, analyzer, boosts);
//设置查询条件
Query query = parser.parse("lucene");
//查询
query(query);
结果如下,可以发现name包含lucene关键字的数据排在了第一位:
共查询到数据总数为:2
ID:1
name:java lucene
price:11.23
pic:null
description:给你推荐一个写得非常用心的Java基础教程:Java入门基础教程 | 天码营这个教程将Java的入门基础知识贯穿在一个实例中,逐步深入,可以帮助你快速进入Java编程的世界。万事开头难,逐步跟着这个教程走一遍,对Java应该就会有一种入门的感觉了。然后再去学习更高级的主题,或者更深入地学习其中的某些知识点。第1课 Java开发环境安装与配置 第2课 第一个Java程序 第3课 面向对象基础 第4课 基本数据类型 第5课 运算符 第6课 字符串操作 第7课 程序的控制流 第8课 静态变量与静态方法 第9课 Java集合 第10课 封装与继承 第11课 抽象类与接口 第12课 异常处理 第13课 综合实例 第14课 Eclipse的安装与使用
作者:David
链接:https://www.zhihu.com/question/25255189/answer/86898400
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
==================================
ID:2
name:solx
price:12.55
pic:null
description:Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。Lucene是一套用于全文检索和搜寻的开源程式库,由Apache软件基金会支持和提供。Lucene提供了一个简单却强大的应用程式接口,能够做全文索引和搜寻。在Java开发环境里Lucene是一个成熟的免费开源工具。就其本身而言,Lucene是当前以及最近几年最受欢迎的免费Java信息检索程序库。人们经常提到信息检索程序库,虽然与搜索引擎有关,但不应该将信息检索程序库与搜索引擎相混淆。[1]
==================================