使用Java的Lucene搜索工具对检索结果进行分组和分页_java

使用GroupingSearch对搜索结果进行分组
Package org.apache.lucene.search.grouping Description

这个模块可以对Lucene的搜索结果进行分组,指定的单值域被聚集到一起。比如,根据”author“域进行分组,“author”域值相同的的文档分成一个组。

进行分组的时候需要输入一些必要的信息:

1、groupField:根据这个域进行分组。比如,如果你使用“author”域进行分组,那么每一个组里面的书籍都是同一个作者。没有这个域的文档将被分到一个单独的组里面。

2、groupSort:组排序。

3、topNGroups:保留多少组。比如,10表示只保留前10组。

4、groupOffset:对排在前面的哪些分组组进行检索。比如,3表示返回7个组(假设opNGroups等于10)。在分页里面很有用,比如每页只显示5个组。

5、withinGroupSort:组内文档排序。注意:这里和groupSort的区别

6、withingroupOffset:对每一个分组里面的哪些排在前面的文档进行检索。

使用GroupingSearch 对搜索结果分组比较简单

GroupingSearch API文档介绍:

Convenience class to perform grouping in a non distributed environment.

非分布式环境下分组

WARNING: This API is experimental and might change in incompatible ways in the next release.

这里使用的是4.3.1版本

一些重要的方法:

  • GroupingSearch:setCaching(int maxDocsToCache, boolean cacheScores) 缓存
  • GroupingSearch:setCachingInMB(double maxCacheRAMMB, boolean cacheScores) 缓存第一次搜索结果,用于第二次搜索
  • GroupingSearch:setGroupDocsLimit(int groupDocsLimit) 指定每组返回的文档数,不指定时,默认返回一个文档
  • GroupingSearch:setGroupSort(Sort groupSort) 指定分组排序

示例代码:

1.先看建索引的代码

public class IndexHelper {
  private Document document;
  private Directory directory;
  private IndexWriter indexWriter;

  public Directory getDirectory(){
    directory=(directory==null)? new RAMDirectory():directory;
    return directory;
  }

  private IndexWriterConfig getConfig() {
    return new IndexWriterConfig(Version.LUCENE_43, new IKAnalyzer(true));
  }

  private IndexWriter getIndexWriter() {
    try {
      return new IndexWriter(getDirectory(), getConfig());
    } catch (IOException e) {
      e.printStackTrace();
      return null;
    }
  }

  public IndexSearcher getIndexSearcher() throws IOException {
    return new IndexSearcher(DirectoryReader.open(getDirectory()));
  }

  /**
   * Create index for group test
   * @param author
   * @param content
   */
  public void createIndexForGroup(int id,String author,String content) {
    indexWriter = getIndexWriter();
    document = new Document();
    document.add(new IntField("id",id, Field.Store.YES));
    document.add(new StringField("author", author, Field.Store.YES));
    document.add(new TextField("content", content, Field.Store.YES));
    try {
      indexWriter.addDocument(document);
      indexWriter.commit();
      indexWriter.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

2.分组:

public class GroupTest

public void group(IndexSearcher indexSearcher,String groupField,String content) throws IOException, ParseException {
    GroupingSearch groupingSearch = new GroupingSearch(groupField);
    groupingSearch.setGroupSort(new Sort(SortField.FIELD_SCORE));
    groupingSearch.setFillSortFields(true);
    groupingSearch.setCachingInMB(4.0, true);
    groupingSearch.setAllGroups(true);
    //groupingSearch.setAllGroupHeads(true);
    groupingSearch.setGroupDocsLimit(10);

    QueryParser parser = new QueryParser(Version.LUCENE_43, "content", new IKAnalyzer(true));
    Query query = parser.parse(content);

    TopGroups<BytesRef> result = groupingSearch.search(indexSearcher, query, 0, 1000);

    System.out.println("搜索命中数:" + result.totalHitCount);
    System.out.println("搜索结果分组数:" + result.groups.length);

    Document document;
    for (GroupDocs<BytesRef> groupDocs : result.groups) {
      System.out.println("分组:" + groupDocs.groupValue.utf8ToString());
      System.out.println("组内记录:" + groupDocs.totalHits);

      //System.out.println("groupDocs.scoreDocs.length:" + groupDocs.scoreDocs.length);
      for (ScoreDoc scoreDoc : groupDocs.scoreDocs) {
        System.out.println(indexSearcher.doc(scoreDoc.doc));
      }
    }
  }

3.简单的测试:

public static void main(String[] args) throws IOException, ParseException {
    IndexHelper indexHelper = new IndexHelper();
    indexHelper.createIndexForGroup(1,"红薯", "开源中国");
    indexHelper.createIndexForGroup(2,"红薯", "开源社区");
    indexHelper.createIndexForGroup(3,"红薯", "代码设计");
    indexHelper.createIndexForGroup(4,"红薯", "设计");
    indexHelper.createIndexForGroup(5,"觉先", "Lucene开发");
    indexHelper.createIndexForGroup(6,"觉先", "Lucene实战");
    indexHelper.createIndexForGroup(7,"觉先", "开源Lucene");
    indexHelper.createIndexForGroup(8,"觉先", "开源solr");

    indexHelper.createIndexForGroup(9,"散仙", "散仙开源Lucene");
    indexHelper.createIndexForGroup(10,"散仙", "散仙开源solr");
    indexHelper.createIndexForGroup(11,"散仙", "开源");
    GroupTest groupTest = new GroupTest();

    groupTest.group(indexHelper.getIndexSearcher(),"author", "开源");
  }
}

4.测试结果:

两种分页方式
Lucene有两种分页方式:

1、直接对搜索结果进行分页,数据量比较少的时候可以用这种方式,分页代码核心参照:

ScoreDoc[] sd = XXX;
// 查询起始记录位置
int begin = pageSize * (currentPage - 1);
// 查询终止记录位置
int end = Math.min(begin + pageSize, sd.length);
for (int i = begin; i < end && i <totalHits; i++) {
//对搜索结果数据进行处理的代码
}

2、使用searchAfter(...)

Lucene提供了五个重载方法,可以根据需要使用

ScoreDoc after:为上次搜索结果ScoreDoc总量减1;

Query query:查询方式

int n:为每次查询返回的结果数,即每页的结果总量

一个简单的使用示例:

//可以使用Map保存必要的搜索结果
Map<String, Object> resultMap = new HashMap<String, Object>();
ScoreDoc after = null;
Query query = XX
TopDocs td = search.searchAfter(after, query, size);

//获取命中数
resultMap.put("num", td.totalHits);

ScoreDoc[] sd = td.scoreDocs;
for (ScoreDoc scoreDoc : sd) {
//经典的搜索结果处理
}
//搜索结果ScoreDoc总量减1
after = sd[td.scoreDocs.length - 1];
//保存after用于下次搜索,即下一页开始
resultMap.put("after", after);

return resultMap;

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索java
, lucene
, 搜索
, 分页
分组
lucene全文检索、lucene 分页、java 全文检索 lucene、lucene 分页查询、lucene 数据库检索,以便于您获取更多的相关知识。

时间: 2024-09-17 03:45:15

使用Java的Lucene搜索工具对检索结果进行分组和分页_java的相关文章

java使用jdbc连接数据库工具类和jdbc连接mysql数据示例_java

这个工具类使用简单,实例化直接调用就可以了,大家还可以方便的根据自己的需要在里面增加自己的功能 复制代码 代码如下: package com.lanp.ajax.db; import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException; /** * 连接数据库的工具类,被定

java自带的工具Jstack截取进程中的堆栈信息_java

在Java软件的使用过程中,有时会莫名的出现奇怪的问题.而这些问题常常无法使用日志信息定位,这时我们就需要通过查看进程内部线程的堆栈调用关系来分析问题出在哪里. 举个例子,当我们在做某个操作时,莫名的会弹出多个警告框,其中有些信息是正常的,有些则不是.对于这些错误的警告信息,我们该如何定位是哪个位置的代码出现了错误弹出的框呢? 我们就需要在弹框以后,去查看软件的各个线程,去查找究竟是哪个线程导致了该问题.可是有时因为环境.时间等问题,我们根本不能拿着IDE去调试, 只能通过工具软件拍下内存快照,

详解Java的Hibernate框架中的搜索工具的运用_java

hibernate提供了全文索引功能,非常棒,这里简要介绍下它的用法, 1. 在pom.xml引入包依赖 <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-search-orm</artifactId> <version>${hibernate-search.version}</version> </dependency> &

产品站长们如何更好利用搜索蜘蛛模拟工具去检索自己首页

摘要: 关于对于产品站长们如何更好利用chinaz工具,在这里我先解释一下为什么要利用搜索蜘蛛模拟工具,其实蜘蛛模拟工具有很大的作用,只是有些站长们根本没有研究.很多学习SEO新站长 关于对于产品站长们如何更好利用chinaz工具,在这里我先解释一下为什么要利用搜索蜘蛛模拟工具,其实蜘蛛模拟工具有很大的作用,只是有些站长们根本没有研究.很多学习SEO新站长们,对于百度蜘蛛模拟工具都不会很好利用.搜索蜘蛛模拟工具更好看到百度蜘蛛从哪里开始爬起. 在这里先解释一下百度蜘蛛的原理,很简单的说一下,百度

字幕搜索工具 V0.0.4.5 下载_常用工具

软件大小: 812 KB  软件语言: 简体中文  软件类别: 国产软件 / 共享版 / 媒体其它  应用平台: Win9x/NT/2000/XP/2003  开 发 商: http://redlegend.51.net/      你是否在为寻找DVDRip电影或者其他影视的字幕而发愁呢? 现在就给你最好的解决办法--"字幕搜索工具". 在网上还没有发现搜索字幕的软件,于是我就自己编了一个. 主要资源来自于射手网,汉风的字幕. 可以查询很多信息,包括:下载连接.语言.版本.调校.翻译

揭开Faiss的面纱 探究Facebook相似性搜索工具的原理

Facebook 开源了 AI 相似性搜索工具 Faiss.而在一个月之后的今天,Facebook 发布了对 Faiss 的官方原理介绍. 它是一个能使开发者快速搜索相似多媒体文件的算法库.而该领域一直是传统的搜索引擎的短板.借助Faiss,Facebook 在十亿级数据集上创建的最邻近搜索(nearest neighbor search),比此前的最前沿技术快 8.5 倍,并创造出迄今为止学术圈所见最快的.运行于 GPU 的 k-selection 算法.Facebook 人工智能实验室(FA

java实现的正则工具类_java

本文实例讲述了java实现的正则工具类.分享给大家供大家参考.具体如下: 这里实现的正则工具类适用于:正则电话号码.邮箱.QQ号码.QQ密码.手机号 java代码如下: package com.zhanggeng.contact.tools; /** * RegexTool is used to regex the string ,such as : phone , qq , password , email . * * @author ZHANGGeng * @version v1.0.1 *

java Socket简易聊天工具_java

本文实例为大家分享了一款Socket简易聊天工具,希望大家喜欢. 代码运行如图,看起来还不错 服务端 package qiu; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.print.Printable; import java.io.BufferedReader; import java.io.IOEx

深入理解java虚拟机的故障处理工具_java

前言 本文主要给大家介绍的是java虚拟机的故障处理工具,文中提到这些工具包括: 名称 主要作用 jps JVM process Status Tool, 显示指定系统内所有的HotSpot虚拟机进程.通常是本地主机 jstat JVM Statistics Monitoring Tool,用于收集HotSpot虚拟机各方面的运行数据 jinfo Configuration Info for java, 显示虚拟机配置信息 jmap Memory Map for Java, 生成虚拟机的内存存储