Java Lucene IndexReader не работает правильно - PullRequest
0 голосов
/ 17 мая 2011

История такая.Я хочу имитировать поведение реляционной базы данных, используя индекс Lucene в Java.Мне нужно уметь одновременно выполнять поиск (чтение) и запись.

Например, я хочу сохранить информацию о проекте в индексе.Для простоты предположим, что в проекте есть 2 поля - id и name.Теперь, прежде чем добавить новый проект в индекс, я ищу, если проект с заданным идентификатором уже существует.Для этого я использую IndexSearcher.Эта операция завершается успешно (а именно: IndexSearcher возвращает внутренний идентификатор документа для документа, который содержит идентификатор проекта, который я ищу).Теперь я хочу на самом деле прочитать значение этого идентификатора проекта, поэтому теперь я использую IndexReader для получения индексированного документа Lucene, из которого я могу извлечь поле идентификатора проекта.Проблема в том, что IndexReader возвращает Document, который имеет все поля NULL.Итак, чтобы повторить, что IndexSearcher работает правильно, IndexReader возвращает поддельные вещи.

Я думаю, что это как-то связано с тем фактом, что данные полей документа не сохраняются на жестком диске при сбросе IndexWriter,Дело в том, что в первый раз, когда я делаю эту операцию индексации, IndexReader работает хорошо.Однако после перезапуска моего приложения, вышеупомянутая ситуация происходит.Поэтому я думаю, что в первый раз данные плавают в оперативной памяти, но не сбрасываются правильно (или полностью, так как 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 ]

1 голос
/ 17 мая 2011

Вы храните соответствующие поля?Если нет, поля «только» хранятся в части обратного индекса, то есть значение поля отображается в документе, но сам документ не содержит значения поля.

Может пригодиться часть кода, в которой вы сохраняете документ.

0 голосов
/ 02 ноября 2011

Мне было трудно понять, как индексировать / искать числа, и я просто хотел сказать, что следующие фрагменты кода действительно помогли мне:

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

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

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

Спасибо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...