【问题标题】:How to calculate avgLengthPath in BM25 implementation for Lucene ( JAVA )如何在 Lucene ( JAVA ) 的 BM25 实现中计算 avgLengthPath
【发布时间】:2012-08-06 05:42:28
【问题描述】:

谁能向我解释如何在 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);
}

建议有一个方法或类来加载平均长度。

希望有任何帮助...

谢谢

【问题讨论】:

    标签: java search lucene indexing


    【解决方案1】:

    我已经解决了这个问题,我想分享我的答案以获得任何更正或 cmets..

    问题是如何计算 avgLengthPath 参数。当我查看采用此参数的方法时:load() 可以看出它需要一个字符串,它是包含平均长度的文件的路径。所以 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);
        }
    }
    

    【讨论】:

    • 我刚刚发现了这个Link,它提供了有关在 Lucene 中运行 BM25 的详细信息。另外,从这个question看来,Lucene 4似乎对BM25有一些支持。
    猜你喜欢
    • 1970-01-01
    • 2020-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多