Java 从Lucene 3.0迁移到4.9.0

Java 从Lucene 3.0迁移到4.9.0,java,api,lucene,Java,Api,Lucene,我想将一个例子从基于Lucene 3.0的《Lucene在行动中的第二版》一书迁移到Lucene的当前版本。以下是需要迁移的代码: public void testUpdate() throws IOException { assertEquals(1, getHitCount("city", "Amsterdam")); IndexWriter writer = getWriter(); Document doc = new Document(); doc.ad

我想将一个例子从基于Lucene 3.0的《Lucene在行动中的第二版》一书迁移到Lucene的当前版本。以下是需要迁移的代码:

public void testUpdate() throws IOException {
    assertEquals(1, getHitCount("city", "Amsterdam"));
    IndexWriter writer = getWriter();
    Document doc = new Document();
    doc.add(new Field("id", "1", Field.Store.YES, Field.Index.NOT_ANALYZED));
    doc.add(new Field("country", "Netherlands", Field.Store.YES, Field.Index.NO));
    doc.add(new Field("contents", "Den Haag has a lot of museums", Field.Store.NO, Field.Index.ANALYZED));
    doc.add(new Field("city", "Den Haag", Field.Store.YES, Field.Index.ANALYZED));
    writer.updateDocument(new Term("id", "1"), doc);
    writer.close();
    assertEquals(0, getHitCount("city", "Amsterdam"));
    assertEquals(1, getHitCount("city", "Den Haag"));
}
我正在尝试根据使用前字段构造函数的等价物来创建文档对象的方法执行迁移。其代码如下所示:

@Test
public void testUpdate() throws IOException
{
   assertEquals(1, getHitCount("city", "Amsterdam"));
   IndexWriter writer = getWriter();
   Document doc = new Document();
   FieldType ft = new FieldType(StringField.TYPE_STORED);
   ft.setOmitNorms(false);
   doc.add(new Field("id", "1", ft));
   doc.add(new StoredField("country", "Netherlands"));
   doc.add(new TextField("contents", "Den Haag has a lot of museums", Store.NO));
   doc.add(new Field("city", "Den Haag", TextField.TYPE_STORED));
   writer.updateDocument(new Term("id", "1"), doc);
   writer.close();
   assertEquals(0, getHitCount("city", "Amsterdam"));
   assertEquals(1, getHitCount("city", "Den Haag");
 }
第二个断言方法失败,因为它找不到字符串“Den Haag”(不过只有“Den”或“Haag”可以工作)。如果改用StringField对象,则测试通过,因为“city”属性未进行分析(即标记化),因此保持不变。但很明显,本示例的目的不是将此属性视为ID。我已经了解到,“Field.Store.YES/Field.Index.analysis”组合适用于小文本内容,如简介文本、摘要或标题,因此它还应匹配串联字符串,如“Den Haag”,或者我错了吗?谁能澄清一下吗

作者使用术语对象创建搜索字符串:

protected int getHitCount(String fieldName, String searchString) throws IOException   {     
    DirectoryReader dr = DirectoryReader.open(directory);   
    IndexSearcher searcher = new IndexSearcher(dr);     
    Term t = new Term(fieldName, searchString);     
    Query query = new TermQuery(t);     
    int hitCount = TestUtil.hitCount(searcher, query);  
    return hitCount;   
} 
TestUtil类只包含一行代码

public static int hitCount(IndexSearcher searcher, Query query) { 
    return searcher.search(query, 1).totalHits;   
}

简短说明:您需要确保索引时和搜索时的标记化设置(开/关)相同

详细解释:如果你想分析你的内容,你不仅应该使用
TextField
,还应该使用
QueryParser
,这样你的查询也会经过同样的过程。在您的情况下,您的查询失败,因为

new Field("city", "Den Haag", TextField.TYPE_STORED));
文本被标记为“Den”和“Haag”。稍后,当您创建
TermQuery
时,您将搜索单个术语“Den Haag”,当然,这不会产生任何结果

下面的代码显示了这如何适用于非标记化的情况:

doc.add(new StringField("city", "Den Haag", Field.Store.YES));
...
PhraseQuery query = new PhraseQuery();
query.addTerm(new Term("city", "Den Haag"));

如何进行搜索(我指的是
getHitCount()
方法)?您是在使用原始
Term
s还是只是在解析查询?@mindas作者使用Term对象创建搜索字符串:
protectedintgethitcount(stringfieldname,stringsearchstring)抛出IOException{DirectoryReader dr=DirectoryReader.open(directory);IndexSearcher searcher=newindexsearcher(dr);术语t=新术语(字段名,搜索字符串);查询查询=新术语查询(t);int hitCount=TestUtil.hitCount(搜索者,查询);返回hitCount;}
。TestUtil类只包含一行代码
public static int hitCount(IndexSearcher,Query Query){return search.search(Query,1.totalHits;}
。很好,使用QueryParser解析查询并使用WhitespaceAnalyzer完成了这项工作。我知道分析步骤在索引时和搜索时必须是相同的,但不知怎的,我认为这会隐式发生。非常感谢你!