2013-11-14 138 views
0

我想建立一个应用程序,实现了Lucene索引的搜索系统。现在索引已经建好了,我可以在索引上搜索文档,并且一切似乎都正常,但是当我使用许多文档中使用的字段进行搜索时,分析器只返回一些文档。我试图使用卢克进行相同的搜索,并采用相同的方式。Lucene的搜索跳过一些结果

例如:我的索引有2个字段:

字段A:唯一的标识符。 字段B:一个字符串。

第一示例:

我们有5个文件:

文件1:FIELDA:1; FieldB:hello world

Doc 2:FieldA:2; FieldB:你好,世界!

Doc 3:FieldA:3; FieldB:hello world

Doc 4:FieldA:4; FieldB:任何东西

Doc 5:FieldA:5; FieldB:世界你好

当我作出这样一个搜索“B:Hello World”的应该返回文件1,3和5,但它只返回1和3

当我作出这样一个搜索“A:5”返回文档5,字段B的值为“hello world”。

第二实例:(一个令牌)

文件6:FIELDA:6; FieldB:token

Doc 7:FieldA:7; FieldB:token

Doc 8:FieldA:8; FieldB:TOKEN

文件9:FIELDA:9 FieldB:令牌

当我搜索FieldB: “令牌” 它只返回文档6和Doc 9.我能找到文件的唯一方法是7通过其FieldA进行搜索。

我使用的是WhitespaceAnalyzer,并且这两个字段都是NOT_ANALYZED。

IndexGenerator主要

... 

IndexWriter writer = new IndexWriter(directory, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.UNLIMITED);; 
writer.setRAMBufferSizeMB(200); 

List<Work> works = getWorks(); //Retrieves the information from the DB 

for (Work work: works) { 

    Document luceneDocument = createLuceneDocument(work); 
    writer.addDocument(luceneDocument); 

} 
writer.commit(); 

... 

CreateLuceneDocument方法:

private static Document createLuceneDocument(Work work) { 

try { 
    Document luceneDoc = new Document(); 

    ... 

    Field id = new Field("ID", work.getId(),Field.Store.YES,Field.Index.NOT_ANALYZED); 
    luceneDoc.add(id); 

    Field name = new Field("NAME", work.getName(),Field.Store.YES,Field.Index.NOT_ANALYZED); 
    luceneDoc.add(name); 

    ... 

    return document; 

    } 
    catch (LuceneException e) { 
     ... 
    } 
} 

我注意到,未返回的文档具有低分值。假设这是索引创建时的问题,因为卢克的行为与应用程序的行为相同,我在做什么错了?

提前致谢!

+0

我没有看到你的例子中会出现这样的问题。我也不明白你怎么能得到一个文件的分数,而你的查询没有找到。也许一些更多的信息是有用的,比如你的搜索代码,以及关于这个问题实际发生的数据的一些进一步的信息? – femtoRgon

+0

谢谢@femtoRgon!这个例子是解释发生的最简单的方法。真实指数超过12个字段,比例子更复杂。 正如我在第一篇文章中所说,即使这些字段满足搜索请求,Luke也不会显示这些文档。所以,问题应该在索引生成过程中。 我将添加更多关于索引生成的信息。 – user2993510

+0

你在哪里看到“未返回的文档具有低分值”? – groverboy

回答

1

Lucene会将搜索表达式B:hello world解析为B:hello D:world,这是一个表达式。这里D是默认搜索字段,可能是您在对@ femtoRgon答案的评论中提到的另一个Field

我猜测结果包括文档1和3,因为它们与字段D中的标记“世界”相匹配,但是此标记在文档5字段D中不存在。但是,只有默认搜索运算符为OR不是,因为B:hello不能匹配这些文件。

您可能会通过使用短语表达式得到您期望的结果:B:"hello world"。但你不可以; WhitespaceAnalyzer将在构建Query对象时将此短语分解为两个令牌。

您可以使用KeywordAnalyzer作为字段B来解决问题,如我的answer to another question中所述。

+0

我在只有1个标记的字段中以及具有多个标记的字段中面临此问题。我正在尝试使用KeywordAnalyzer与卢克一起搜索,但是我得到了相同的结果,也许是因为索引是使用WhitespaceAnalyzer生成的,但它是否影响到1个标记字段?感谢您的帮助@groverboy! – user2993510

+0

@ user2993510取决于“1令牌字段”的含义。需要说明的是,如果字段B,值为“hello world”的值是用NOT_ANALYZED创建的,那么该字段有1个标记[hello world]。如果字段C的值“hello world”是使用'ANALYZED'创建的,那么该字段有2个标记[hello] [world]。 – groverboy

+0

@ user2993510请给出一个你试过用'KeywordAnalyzer'使用Luke的例子搜索表达式? – groverboy

1

我想给你我的怀疑,我想。您说您正在使用WhitespaceAnalyzer,但由于您的字段为NOT_ANALYZED,该分析程序对索引内容没有任何作用。它们被完全按原样编入索引,作为单个标记。

如果您将索引值“hello there”,在“hello”上搜索TermQuery将找不到任何内容。如果您编入索引“你好”,“你好!”,甚至“你好”,它也不会找到任何东西。这将是大小写,标点符号,空格等敏感,并且需要匹配整个输入。所以我怀疑你的未找到的文件在这些方面有问题。

+0

这是正确的@femtoRgon,我想这些字段被索引为一个单一的标记,因为我正在使用另一个'Field'来使用不同的标记索引相同的值。问题是我正在搜索“hello world”,并且只找到了3个文档中的2个(我已经对该示例进行了一些更改以阐明此问题)。再次感谢! – user2993510

+0

+1 @femtoRgon帮助我回答一个不太清楚的问题。 – groverboy