前段时间同事也开始对搜索感兴趣,他看到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
分享到:
相关推荐
《Nluke索引文件查看器:深入理解Lucene索引机制》 在信息技术日新月异的今天,搜索引擎已经成为我们获取信息的重要途径。而在这个领域中,Apache Lucene作为一个强大的开源全文搜索引擎库,被广泛应用于各种信息...
Luke 是一个非常实用的 Lucene 索引浏览器,全称为 Lucidworks Luke。它允许用户以图形化的方式查看、操作和分析 Lucene 索引。 Luke 提供了诸如查看文档字段、搜索索引、查看倒排索引结构等功能,对于开发者来说是...
这种方式虽然全面,但可能导致索引文件过大,影响检索速度。 - **ChineseAnalyzer**:与`StandardAnalyzer`类似,也是按字分词。 - **CJKAnalyzer**:按两字切分,可能产生无意义的词元(Token),影响索引的质量。 ...
2. **索引构建**: 对每个词元创建Term对象,并记录其在文档中的位置和频率,然后存储这些信息到倒排索引中。 3. **查询解析**: 用户输入的查询字符串经过相同的分析过程,转换成一系列Term对象。 4. **搜索**: 使用...
然后,为每个要索引的文档创建一个 Document 对象,添加字段,并使用 IndexWriter 将其写入索引。 2. **索引文档**:对于每个字段,可以使用 Analyzer 分析文本并创建 Term。然后,使用 Document 的 add 方法将 ...
索引文件通常包含了文档的标识符、词汇表(包括词项及其出现的位置)、文档频率、逆文档频率(IDF)等信息。这些信息对于后续的检索过程至关重要,它们共同构成了全文检索系统的基础。 ##### 3. 如何创建索引 创建...
3. 词项(Term)创建:每个分词都会被转换为一个Term对象,包含词元和位置信息。 4. 文档(Document)创建:每个文档由多个字段(Field)组成,如标题、内容等,每个字段对应一个或多个Term。 5. 倒排索引(Inverted...
每个关键词都有一个唯一的标识符(Term ID),便于计算机处理。 2. 倒排文件:对于每个词汇表中的关键词,都有一个对应的倒排列表,记录了包含该词的所有文档及其在文档内的位置信息。这使得搜索引擎能快速找到包含...
索引过程中,分析器会作用于每个字段的文本,生成一个倒排索引,用于后续的搜索操作。 4. **搜索(Searching)**:使用QueryParser创建查询对象,然后使用IndexSearcher执行搜索。根据查询结果,我们可以获取匹配的...
2. 字符串到Term:将分词结果转化为Term对象,每个Term代表一个唯一的词汇项。 3. 建立Term Frequency(TF):记录每个文档中每个Term出现的频率。 4. 建立Inverted Index:将Term作为键,文档ID和TF作为值,构建倒...
Lucene是一个基于Java的全文索引引擎工具包,它并不是一个完整的全文搜索引擎,而是提供了一套构建搜索引擎的基础组件。Lucene的主要目标是方便开发者将其集成到各类应用程序中,以实现高效的全文检索功能。其API...
通过实例,我们可以创建一个简单的索引器,将文本文件或数据库内容导入Lucene索引,然后编写一个搜索引擎来查询这些内容。这通常涉及以下步骤: - 创建索引:定义Document结构,使用Analyzer处理Field,通过...
例如,TF-IDF是一种经典的文档表示方法,它通过结合词频(Term Frequency, TF)和逆文档频率(Inverse Document Frequency, IDF)来衡量一个词在文档中的重要性。 在Java实现中,开发者可能会用到如`java.io`和`...
### Lucene的索引文件格式 Lucene使用特定的文件格式存储索引信息,包括正向信息(如文档元数据)、反向信息(如词典和文档频率信息)和其他辅助信息。例如,`segments_N`文件存储了当前索引的段信息,`.fnm`和`.fdt...
1. Lucene概述:Lucene是一个开源的Java库,它提供了索引和搜索文本所需的全部工具。其核心功能包括分词、建立倒排索引、查询解析和结果排序等。 2. Lucene组件: - 分析器(Analyzer):处理文本,将其转化为可被...
2. 匹配与评分:查询执行时,Query对象与索引进行匹配,每个匹配的文档都会获得一个评分,这个评分基于Term频率、文档频率等因素。 3. 结果排序:默认情况下,Lucene根据评分进行结果排序,高分的文档优先展示。 ...
可以将每个文件的关键字及其位置存储在一个数据结构(如数组或数据库)中。 - 使用PHP的数组或关联数组存储索引,键为关键字,值为文件信息。 5. **查询处理** - 用户输入查询后,PHP程序需解析查询,然后在索引...
#### Lucene的索引文件格式 **Lucene**采用了一种高效的文件格式来存储索引信息,主要包括: 1. **正向信息**: - **段的元数据信息**: 包括版本信息、段名称等。 - **域的元数据信息**: 记录每个字段的信息。 -...