История такая.Я хочу имитировать поведение реляционной базы данных, используя индекс 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"));
}
В другой ветке ... Я не знаю, что не так.