任何人都可以向我解释如何在Lucene的BM25实现中计算'avgLengthPath'变量。我的理解是我必须在索引期间计算它。但仍然不清楚如何这样做。
提供的示例:
IndexSearcher searcher = new IndexSearcher("IndexPath");
//Load average length
BM25Parameters.load(avgLengthPath);
BM25BooleanQuery query = new BM25BooleanQuery("This is my Query",
"Search-Field",
new StandardAnalyzer());
TopDocs top = searcher.search(query, null, 10);
ScoreDoc[] docs = top.scoreDocs;
//Print results
for (int i = 0; i $<$ top.scoreDocs.length; i++) {
System.out.println(docs[i].doc + ":"+docs[i].score);
}
建议有一种方法或类来加载平均长度。
非常感谢任何帮助...
由于
答案 0 :(得分:1)
我已经解决了这个问题,我想与大家分享一些答案,以获得任何更正或评论。
问题是如何计算avgLengthPath参数。当我查看采用此参数的方法:load()
时,可以看到它需要一个String,它是包含平均长度的文件的路径。所以 avgLengthPath 会是这样的:
/Users/admib/Study/avgLength
load()
方法如下:
public static void load(String path) throws NumberFormatException,
IOException {
BufferedReader in = new BufferedReader(new FileReader(path));
String line;
while (null != (line = in.readLine())) {
String field = line;
Float avg = new Float(in.readLine());
BM25Parameters.setAverageLength(field, avg);
}
in.close();
}
现在,以免看到如何创建这样的文件。我们可以看到上面的方法逐行读取文件,并将每两行发送到另一个名为BM25Parameters.setAverageLength()
的方法。 avgLengthPath文件的格式应该是这样的:
CONTENT
459.2903f
ANCHOR
84.55523f
第一行是字段名称,第二行是此字段的平均长度。 此外,第三行是另一个字段,第四行是该字段的平均长度。
关于这样的文件的问题是我们无法从Lucene的默认坐位获取文档长度。为了解决这个问题,我重新编制了我的集合索引,并将文档长度添加为Lucene要编入索引的字段之一。
首先,我创建了一个获取文件并将文档长度作为字符串返回的方法。我称之为getDocLength(File f)
:
public static String getDocLength(File f) throws IOException {
FileInputStream stream = new FileInputStream(f);
try {
FileChannel fc = stream.getChannel();
MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
String doc = Charset.defaultCharset().decode(bb).toString();
int length = doc.length();
return Integer.toString(length);
} finally {
stream.close();
}
}
在索引过程中调用此方法以添加文档长度字段,如下所示:
protected Document getDocument(File f) throws Exception {
Document doc = new Document();
String docLength = Integer.toString(io.getDocLength(f));
doc.add(new Field("contents", new FileReader(f), Field.TermVector.YES));
doc.add(new Field("docLength", i, Field.Store.YES, Field.Index.NOT_ANALYZED));
doc.add(new Field("filename", f.getName(), Field.Store.YES, Field.Index.NOT_ANALYZED));
doc.add(new Field("fullpath", f.getCanonicalPath(), Field.Store.YES, Field.Index.NOT_ANALYZED));
return doc;
}
最后,我创建了一个方法,循环索引中的所有文档并计算平均文档长度,最后将结果保存到带有正确格式的 avgLengthPath 文件中。我称这种方法为generateAvgLengthPathFile()
:
public static void generateAvgLengthPathFile(String luceneIndexPath, String outputFilePath) {
try {
Directory dir = FSDirectory.open(new File(luceneIndexPath));
IndexReader reader = IndexReader.open(dir);
int totalLength = 0;
//here we loop through all the docs in the index
for (int i = 0; i < reader.maxDoc(); i++) {
if (reader.isDeleted(i)) {
continue;
}
Document doc = reader.document(i);
totalLength += Integer.parseInt(doc.get("docLength"));
}
//calculate the avarage length
float avarageLength = totalLength * 1.0f / reader.maxDoc() * 1.0f;
//create the a String varibale with the correct formate
String avgLengthPathFile = "contents" + "\n" + avarageLength;
//finally, save the file
Writer output = null;
String text = "contents" + "\n" + avarageLength;
File file = new File(outputFilePath);
output = new BufferedWriter(new FileWriter(file));
output.write(text);
output.close();
} catch (Exception e) {
System.err.println(e);
}
}