前段时间同事也开始对搜索感兴趣,他看到luke工具界面上会显示Term的频率数,提出通过索引用户的搜索日志中的检索关键字,我们是否可以利用这个Field字段中Term频率高低来说明其是否代表热点关键字。
想想觉得也是有一点在理,特别是对用户没有任何可分析性的情况下。但这就引出了一个问题:如何获取整个索引文件里频率最高的哪几个Term?
翻了几次API,网上也搜了但没找到什么信息,仅仅看到网上有一篇文章讲到通过IndexReader取出所有的Term,然后再比较每一个的频率,最终得出最高频率的哪几个Term。但这又让我们顾虑的是当大数据量时如何确保其速度?
既然luke可以在界面上展示出来,那它一定实现了这个功能,所以今天下了源代码,不过发现其已经不支持Lucene3.0.2,查看更新日志原来他们已经更新到可兼容未来Lucene4.0.0版本。最后从日志里找出已被删除的两个java文件:HighFreqTerms.java 和TermInfo.java,源代码如下(本人在里面添加了注释,如有错误请大家帮忙纠正,:-D):
import org.apache.lucene.index.Term;
public class TermInfo {
public Term term;
public int docFreq; //term频率
public TermInfo(Term t, int df) {
this.term = t;
this.docFreq = df;
}
}
import org.apache.lucene.util.PriorityQueue;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.TermEnum;
import java.io.File;
import java.util.Hashtable;
/**
* 获取一个索引文件中最高频率Term数组
* <code>HighFreqTerms</code> class extracts terms and their frequencies out
* of an existing Lucene index.
*
* @version $Id: HighFreqTerms.java,v 1.2 2003/11/08 10:55:40 Administrator Exp $
*/
public class HighFreqTerms {
public static int defaultNumTerms = 10; //初始化默认取出top defaultNumTerms-1条
public static void main(String[] args) throws Exception {
Directory dir = FSDirectory.open(new File("D:\\DATAMANAGER\\INDEX\\SYS_3000"));
TermInfo[] terms = getHighFreqTerms(IndexReader.open(dir), null, new String[]{"content"});
for (int i = 0; i < terms.length; i++) {
System.out.println(i + ".\t" + terms[i].term+":"+terms[i].docFreq);
}
}
/**
* 取出频率最高的term列表
* @param ir IndexReader
* @param junkWords Hashtable 过滤词
* @param fields 可获取多个Field new String[]{"title","content"}
* @return TermInfo[]
* @throws Exception
*/
public static TermInfo[] getHighFreqTerms(IndexReader ir, Hashtable junkWords, String[] fields) throws Exception {
return getHighFreqTerms(ir, junkWords, defaultNumTerms, fields);
}
/**
* 取出频率最高的term列表
* @param reader IndexReader
* @param junkWords Hashtable 过滤词
* @param numTerms 初始化队列的大小即取出numTerms-1条
* @param fields 可获取多个Field new String[]{"title","content"}
* @return TermInfo[]
* @throws Exception
*/
public static TermInfo[] getHighFreqTerms(IndexReader reader, Hashtable junkWords, int numTerms, String[] fields) throws Exception {
if (reader == null || fields == null) return null;
TermInfoQueue tiq = new TermInfoQueue(numTerms); //实例化一个numTerms大小存放TermInfo的队列
TermEnum terms = reader.terms(); //读取索引文件里所有的Term
int minFreq = 0; //队列最后一个Term的频率即当前最小频率值
while (terms.next()) {//取出一个Term对象出来
String field = terms.term().field();
if (fields != null && fields.length > 0) {
boolean skip = true; //跳过标识
for (int i = 0; i < fields.length; i++) {
if (field.equals(fields[i])) { //当前Field属于fields数组中的某一个则不跳过
skip = false;
break;
}
}
if (skip) continue;
}
//当前term的内容是过滤词,则直接跳过
if (junkWords != null && junkWords.get(terms.term().text()) != null) continue;
//获取最高频率term的核心代码
//(队列底层是最大频率Term,顶层是最小频率Term,当插入一个元素后超出初始化队列大小则pop最上面的那个元素,重新设置最小频率值minFreq)
if (terms.docFreq() > minFreq) {//当前Term的频率大于最小频率则插入队列中
tiq.insertWithOverflow(new TermInfo(terms.term(), terms.docFreq()));
if (tiq.size() >= numTerms) // if tiq overfull 当队列中的个数大于numTerms
{
tiq.pop(); // remove lowest in tiq 取出最小频率的元素即最上面的一个元素
minFreq = ((TermInfo)tiq.top()).docFreq; // reset minFreq 重新设置当前最顶层Term的频率为minFreq
}
}
}
//pop出队列元素,最终存放在数组中元素的term频率按从大到小排列
TermInfo[] res = new TermInfo[tiq.size()];
for (int i = 0; i < res.length; i++) {
res[res.length - i - 1] = (TermInfo)tiq.pop();
}
return res;
}
}
//队列,用于term频率比较的队列
final class TermInfoQueue extends PriorityQueue<TermInfo> {
TermInfoQueue(int size) {
initialize(size);
}
protected final boolean lessThan(TermInfo a, TermInfo b) {
return a.docFreq < b.docFreq;
}
}
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/foamflower/archive/2010/12/01/6048672.aspx
分享到:
相关推荐
索引类型-说明 索引文件有数据文件和索引表文件组成。 索引表中存放记录的关键字和记录在文件中的位置。 多级索引。
模拟设计物理文件的存储过程(连续文件、索引文件)
文件索引的创建 文件索引的创建 文件索引的创建 文件索引的创建 文件索引的创建 文件索引的创建
检查索引文件与实际数据文件的一致性,需满足索引文件中的文件名与实际文件文件名一致
索引文件中每一项就是文件名,可以无扩展名,可以包含属性,按所属目录进行分类。文件名每一项可以进行连续编号,也可以按目录分别进行编号,还可以不要编号,可以选择编号方式。目录名单独编号。 该软件简单易用,...
索引文件中每一项就是文件名,可以无扩展名,可以包含属性,按所属目录进行分类。文件名每一项可以进行连续编号,也可以按目录分别进行编号,还可以不要编号,可以选择编号方式。目录名单独编号。 该软件简单易用...
每个索引节点(I节点)有十三个地址项,10个直接地址项,1个一级索引地址,1个二级索引地址,1个三级索引地址,给你一个文件大小通过计算能得知该文件占了那些块。(此为C++编写,仅供参考)
索引文件中每一项就是文件名,按所属目录进行分类,文件名每一项可以进行连续编号,也可以按目录分别进行编号,还可以不要编号,可以选择编号方式。目录名单独编号。 该软件简单易用,方便用于文档编辑的人进行...
SQL SERVER索引文件迁移到文件组,可以将索引和数据文件分在不同的文件组中,实现物理分离,便于管理
操作系统实验,使用vc,实现混合索引文件系统! 支持创建文件目录,查找文件和目录,显示目录内容!显示文件和目录所在盘块! 操作系统实验,使用vc,实现混合索引文件系统! 支持创建文件目录,查找文件和目录,...
操作系统模拟实现单级目录、单级索引的索引文件系统课设报告
这里我讲一下自己扩充nachos二级文件索引的解题过程。做一道试验题,总会遇到很多问题,而在解决问题的同时,也是提高能力的过程。
模拟设计物理文件的存储过程——串联文件、索引文件,其中有代码,实现了多级索引,个人原创。
非常不错的索引文件查看工具!大家可以试试!
windows 环境下对所有文件进行全盘检索,不必记住相应路径。 免安装,支持正则等操作。==============
源码里面的路径需要自己改变,测试数据为utf-8编码,源码里面附有gb转...里面的方法适用与建立简单的文件内容索引(把文本作为数据库)。没用二进制的存取方式是为了c++和php兼容。(简单的模仿了FAT(文件分配表))
索引结构文件包括一级索引,二级索引 #include #include #include #include #include #define BLOCKNUM 8000 //磁盘物理块个数 #define DIRECT_ADDR_NUM 10 //直接寻址地址个数 #define INDEXTABLE_NUM 100 //...
lukeall,Lucene索引文件查看工具可支持Lucene4.7版本的索引查看,直接双击打开,选择索引目录进行使用
利用SBT树写的一个文件-地址偏移的类,用来实现文件索引存储~~利用SBT树写的一个文件-地址偏移的类,用来实现文件索引存储~~利用SBT树写的一个文件-地址偏移的类,用来实现文件索引存储~~
索引文件中每一项就是文件名,可以无扩展名,可以使用通配符,可以包含属性,按所属目录进行分类。 3. 文件名每一项可以进行连续编号,也可以按目录分别进行编号,还可以不要编号,可以选择编号方式。目录名单独...