【问题标题】:Lucene search skips some resultsLucene 搜索会跳过一些结果
【发布时间】:2013-11-27 23:59:57
【问题描述】:

我正在尝试构建一个通过 Lucene 索引实现搜索系统的应用程序。现在索引已建立,我可以在索引上搜索文档,一切似乎都工作正常,但是当我使用许多文档中使用的字段进行搜索时,分析器只返回一些文档。我尝试使用 Luke 进行相同的搜索并且行为方式相同。

即:我的索引有 2 个字段:

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

第一个例子:

我们有 5 个文件:

文档 1:字段 A:1;字段B:你好世界

文档 2:字段 A:2; FieldB:世界你好!

文档 3:字段A:3;字段B:你好世界

文件 4:FieldA:4;字段B:任何东西

文档 5:字段A:5;字段B:你好世界

当我进行像“B: hello world”这样的搜索时,它应该返回文档 1、3 和 5,但它只返回 1 和 3。

当我进行像“A: 5”这样的搜索时,它会返回文档 5,字段 B 的值是“hello world”。

第二个例子:(一个令牌)

文档 6:字段 A:6;字段B:令牌

文档 7:字段A:7;字段B:令牌

文档 8:字段A:8;字段B:TOKEN

文档 9:FieldA:9 FieldB:token

当我搜索 FieldB:"token" 时,它只返回 Doc 6 和 Doc 9。我能找到 Doc 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) {
       ...
   }
}

我注意到未返回的文档的分值较低。假设在创建索引时这是一个问题,因为 Luke 的行为方式与应用程序相同,那么我做错了什么?

提前致谢!

【问题讨论】:

  • 我在您的示例中看不到任何会导致此类问题的内容。我也不明白您如何为查询中未找到的文档评分。也许更多信息会很有用,例如您的搜索代码,以及有关实际发生此问题的数据的更多信息?
  • 感谢@femtoRgon!该示例是解释正在发生的事情的最简单方法。真正的索引有超过 12 个字段,并且比示例复杂得多。正如我在第一篇文章中所说,即使字段满足搜索请求,Luke 也不会显示文档。所以,问题应该出在索引生成过程上。我将添加有关索引生成的更多信息。
  • 您在哪里看到“未返回的文档具有低分值”?
  • 我有 2 个字段具有相同的值,第一个字段没有分析,我有问题,第二个字段有标记,分析后可以正常工作。我尝试在第一个字段中搜索“hello world”并得到 2 个结果,第二个字段中的相同搜索返回 3 个字段(按照示例)。当我尝试仅使用一个标记搜索字符串时也会发生同样的情况,因此问题与标记无关。当我按第二个字段搜索时,我得到第一个字段搜索未返回的文档,即使字段值相同,所有这些文档的分值都非常低。

标签: lucene luke


【解决方案1】:

我想我只是在这里给你我的怀疑,我想。您说您正在使用WhitespaceAnalyzer,但由于您的字段是NOT_ANALYZED,因此该分析器不会对索引内容做任何事情。它们按原样作为单个标记准确地编入索引。

如果您正在索引值“hello there”,则在“hello”上使用TermQuery 搜索将找不到任何内容。如果您索引了“Hello”、“hello!”甚至“hello”,它也不会找到任何东西。它将区分大小写、标点符号、空格等,并且需要对整个输入进行匹配。所以我怀疑,您未找到的文档在这些方面存在问题。

【讨论】:

  • 没错@femtoRgon,我希望将这些字段作为单个标记进行索引,因为我正在使用另一个Field 来使用不同的标记来索引相同的值。问题是我正在搜索“hello world”,并且只找到了 3 个文档中的 2 个(我对示例进行了一些更改以澄清这一点)。再次感谢!
  • +1 @femtoRgon 帮助我回答了一个不太清楚的问题。
【解决方案2】:

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

我猜结果包括文档 1 和 3,因为它们匹配字段 D 中的标记“world”,但文档 5 字段 D 中不存在此标记。但这只有在默认搜索运算符为 OR not 时才有可能并且,因为B:hello 无法匹配这些文档。

使用短语表达式:B:"hello world",您可能会得到您期望的结果。但你可能不会; WhitespaceAnalyzer 在构建 Query 对象时会将这个短语分成两个标记。

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

【讨论】:

  • 我在只有 1 个标记的字段以及具有多个标记的字段中都面临这个问题。我正在尝试使用 KeywordAnalyzer 使用 Luke 进行搜索,但我得到了相同的结果,可能是因为索引是使用 WhitespaceAnalyzer 生成的,但它会影响 1 个令牌字段吗?感谢您的帮助@groverboy!
  • @user2993510 取决于“1 个令牌字段”的含义。为了清楚起见,如果字段 B,值“hello world”是用NOT_ANALYZED 创建的,那么该字段有 1 个标记 [hello world]。如果字段 C,使用 ANALYZED 创建值“hello world”,则该字段有 2 个标记 [hello] [world]。
  • @user2993510 请给出一个您尝试使用 Luke 和 KeywordAnalyzer 的搜索表达式示例?
  • 我在解释中添加了另一个示例来澄清这一点。我试图解释说,如果我使用一两个令牌进行搜索,这并不重要。如果我搜索“hello world”,我将无法获得所有结果,如果我只使用一个标记进行搜索,就像第二个带有“token”的示例一样。即我在 Luke 中搜索这个:FieldB:token。
  • @user2993510 - 你混淆了 word 和 token,它们是不同的东西。无论如何,如果您想要字段 B NOT_ANALYZED 并且该字段中可能有多个单词,您需要使用 KeywordAnalyzer(或其他非标记分析器)both 进行索引和搜索。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-26
相关资源
最近更新 更多