2011-05-16 104 views
0

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

例如,我想将项目信息保存到索引中。为了简单起见,假设该项目有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")); 
    } 

在else分支... 我不知道什么是错。

回答

1

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

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

+0

是啊!就是这样。被很多索引弄糊涂了。谢谢! – 2011-05-16 21:07:24

0

我有一个很难搞清楚如何索引/搜索号,我只是想说,下面的代码片段真的帮了我:

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

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

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

谢谢!