Java Lucene IndexReader无法正常工作

时间:2011-05-16 20:15:28

标签: java indexing lucene

故事是这样的。我想在java中使用Lucene索引模仿关系数据库的行为。我需要能够同时进行搜索(阅读)和写作。

例如,我想将项目信息保存到索引中。为简单起见,假设项目有2个字段 - id和name。现在,在向索引添加新项目之前,我正在搜索具有给定id的项目是否已经存在。为此,我使用的是IndexSearcher。此操作成功完成(即IndexSearcher返回包含我正在查找的项目ID的文档的内部文档ID)。 现在我想实际读取这个项目ID的值,所以我现在使用一个IndexReader来获取索引的Lucene文档,我可以从中提取项目ID字段。 问题是IndexReader返回一个包含所有字段为NULL的Document。因此,要重复IndexSearcher正常工作,IndexReader会返回伪造的内容。

我认为这与文件字段数据在刷新IndexWriter时不会保存在硬盘上的事实有关。问题是我第一次做这个索引操作时,IndexReader工作得很好。但是,在重新启动我的应用程序后,会出现上述情况。所以我认为第一次数据浮动在RAM中,但是在硬盘驱动器上没有正确刷新(或完全自IndexSearcher起作用)。

如果我给你源代码,也许会有所帮助,所以在这里(你可以放心地忽略tryGetIdFromMemory部分,我正在使用它作为速度优化技巧):

public class ProjectMetadataIndexer {
private File indexFolder;
private Directory directory;
private IndexSearcher indexSearcher;
private IndexReader indexReader;
private IndexWriter indexWriter;
private Version luceneVersion = Version.LUCENE_31;

private Map<String, Integer> inMemoryIdHolder;
private final int memoryCapacity = 10000;

public ProjectMetadataIndexer() throws IOException {
    inMemoryIdHolder = new HashMap<String, Integer>();

    indexFolder = new File(ConfigurationSingleton.getInstance()
            .getProjectMetaIndexFolder());

    directory = FSDirectory.open(indexFolder);
    IndexWriterConfig config = new IndexWriterConfig(luceneVersion,
            new WhitespaceAnalyzer(luceneVersion));
    indexWriter = new IndexWriter(directory, config);

    indexReader = IndexReader.open(indexWriter, false);

    indexSearcher = new IndexSearcher(indexReader);

}

public int getProjectId(String projectName) throws IOException {
    int fromMemoryId = tryGetProjectIdFromMemory(projectName);
    if (fromMemoryId >= 0) {
        return fromMemoryId;
    } else {
        int projectId;

        Term projectNameTerm = new Term("projectName", projectName);
        TermQuery projectNameQuery = new TermQuery(projectNameTerm);

        BooleanQuery query = new BooleanQuery();
        query.add(projectNameQuery, Occur.MUST);

        TopDocs docs = indexSearcher.search(query, 1);
        if (docs.totalHits == 0) {
            projectId = IDStore.getInstance().getProjectId();
            indexMeta(projectId, projectName);
        } else {
            int internalId = docs.scoreDocs[0].doc;
            indexWriter.close();
            indexReader.close();
            indexSearcher.close();

            indexReader = IndexReader.open(directory);
            Document document = indexReader.document(internalId);
            List<Fieldable> fields = document.getFields();
            System.out.println(document.get("projectId"));
            projectId = Integer.valueOf(document.get("projectId"));
        }

        storeInMemory(projectName, projectId);

        return projectId;
    }
}

private int tryGetProjectIdFromMemory(String projectName) {
    String key = projectName;
    Integer id = inMemoryIdHolder.get(key);
    if (id == null) {
        return -1;
    } else {
        return id.intValue();
    }
}

private void storeInMemory(String projectName, int projectId) {
    if (inMemoryIdHolder.size() > memoryCapacity) {
        inMemoryIdHolder.clear();
    }
    String key = projectName;
    inMemoryIdHolder.put(key, projectId);
}

private void indexMeta(int projectId, String projectName)
        throws CorruptIndexException, IOException {
    Document document = new Document();

    Field idField = new Field("projectId", String.valueOf(projectId),
            Store.NO, Index.ANALYZED);
    document.add(idField);

    Field nameField = new Field("projectName", projectName, Store.NO,
            Index.ANALYZED);
    document.add(nameField);

    indexWriter.addDocument(document);
}

public void close() throws CorruptIndexException, IOException {
    indexReader.close();
    indexWriter.close();
}

}

更准确地说,如果出现以下所有问题:

if (docs.totalHits == 0) {
        projectId = IDStore.getInstance().getProjectId();
        indexMeta(projectId, projectName);
    } else {
        int internalId = docs.scoreDocs[0].doc;

        Document document = indexReader.document(internalId);
        List<Fieldable> fields = document.getFields();
        System.out.println(document.get("projectId"));
        projectId = Integer.valueOf(document.get("projectId"));
    }

在其他分支上...... 我不知道出了什么问题。

2 个答案:

答案 0 :(得分:1)

你是store各自的领域吗?如果不是,则字段“仅”存储在反向索引部分中,即字段值被映射到文档,但是文档本身不包含字段值。

保存文档的代码部分可能会有所帮助。

答案 1 :(得分:0)

我很难弄清楚如何索引/搜索数字,我只是想说下面的代码片段真的帮助了我:

projectId = Integer.valueOf(document.get("projectId"));

////////////

Field idField = new Field("projectId", String.valueOf(projectId),
            Store.NO, Index.ANALYZED);
    document.add(idField);

谢谢!