繁体   English   中英

Lucene Index带有“ - ”字符的问题

[英]Lucene Index problems with “-” character

我在使用包含“ - ”字符的索引单词的Lucene索引时遇到问题。

它适用于包含“ - ”的一些单词,但不适用于所有单词,我找不到原因,为什么它不起作用。

我正在搜索的字段被分析并包含带有和不带“ - ”字符的单词的版本。

我正在使用分析器:org.apache.lucene.analysis.standard.StandardAnalyzer

这里有一个例子:

如果我搜索“gsx- *”我得到一个结果,索引字段包含“SUZUKI GSX-R 1000 GSX-R1000 GSXR”

但如果我搜索“v- *”,我就没有结果。 预期结果的索引字段包含:“SUZUKI DL 1000 V-STROM DL1000V-STROMVSTROM V STROM”

如果我搜索没有“*”的“v-strom”它可以工作,但如果我只是搜索“v-str”,例如我没有得到结果。 (应该有一个结果,因为它是用于网上商店的实时搜索)

那么,2个预期结果之间有什么区别? 为什么它适用于“gsx- ”而不适用于“v- ”?

我相信,StandardAnalyzer会将连字符视为空格。 因此,它将您的查询"gsx-*"变为"gsx*""v-*"因为它也消除了单字母标记。 您在搜索结果中看到的字段内容是字段的存储值,它完全独立于为该字段编制索引的字词。

所以你想要的是“v-strom”作为一个整体成为一个索引术语。 StandardAnalyzer不适合此类文本。 也许可以使用WhitespaceAnalyzerSimpleAnalyzer 如果仍然不剪,你也有拼凑自己的分析,还是刚刚开始关闭这两个mentined,并进一步将它们组成的选项TokenFilters Lucene Analysis软件包Javadoc给出了一个非常好的解释

顺便说一句,没有必要输入索引中的所有变体,比如V-strom,V-Strom等。这个想法是让同一个分析器在索引和解析查询时将所有这些变体规范化为相同的字符串。

ClassicAnalyzer将 ' - '作为有用的非分隔符处理。 据我了解ClassicAnalyzer,它像3.1之前的StandardAnalyzer一样处理' - ',因为ClassicAnalyzer使用ClassicTokenizer来处理带有嵌入式' - '作为产品代码的数字,因此整个事物被标记为一个术语。

当我在Regenstrief研究所时,我在升级Luke之后注意到这一点,因为LOINC标准医学术语(LOINC由RI发起)通过一个数字后跟一个' - '和一个校验位来识别,如'1-8'或'2857 -1' 。 我在Luke 3.5.0中使用StandardAnalyzer时,我对LOINC的搜索失败了,例如'45963-6',但是在ClassicAnalyzer中成功了(这是因为我们使用2.9.2 Lucene.NET构建了索引)。

(基于Lucene 4.7) StandardTokenizer将带连字符的单词拆分为两个。 例如“聊天室”进入“聊天室”,“房间”并分别索引两个单词,而不是索引为单个整个单词。 单独的单词用连字符连接是很常见的:“运动疯狂”,“准备相机”,“快速思考”等等。 很多都是带连字符的名称,例如“Emma-Claire”。在进行全字搜索或查询时,用户希望在这些连字符中找到该单词。 虽然在某些情况下它们是单独的单词,但这就是lucene将连字符保留在默认定义之外的原因。

要在StandardAnalyzer支持连字符,您必须在StandardTokenizerImpl.java中进行更改,该更改是从jFlex生成的类。

请参阅此链接以获取完整指南。

您必须在SUPPLEMENTARY.jflex-macro添加以下行,该行包含在StandardTokenizerImpl.jflex文件中。

 MidLetterSupp = ( [\u002D]  ) 

在进行更改后,将StandardTokenizerImpl.jflex文件作为jFlex引擎的输入,然后单击generate。 它的输出将是StandardTokenizerImpl.java

并使用该类文件重建索引。

建议ClassicAnalzer索引包含“GSX-R1000”等产品代码的文本。 它会认为这是一个单独的术语,并没有将其部分分开。 但是,例如,“欧洲/柏林”文本将由ClassicAnalzer分为“欧洲”和“柏林”。 这意味着如果您有包含短语的ClassicAnalyzer索引的文本

Europe/Berlin GSX-R1000

你可以搜索“欧洲”,“柏林”或“GSX-R1000”。

但要小心你用于搜索的分析仪。 我认为搜索Lucene索引的最佳选择是KeywordAnalyzer。 使用KeywordAnalyzer,您还可以搜索文档中的特定字段,并可以构建复杂的查询,如:

(processid:4711) (berlin) 

此查询将使用短语“berlin”搜索文档,但也会搜索包含编号4711的字段“processid”。

但是,如果你在索引中搜索“欧洲/柏林”这个词,你将得不到任何结果! 这是因为KeywordAnalyzer没有改变你的搜索短语,但ClassicAnalyzer将短语“Europe / Berlin”分成两个单独的单词。 这意味着您必须分别搜索“欧洲”和“柏林”。

要解决此冲突,您可以使用以下代码在符合您需要的搜索查询中翻译用户输入的搜索词:

QueryParser parser = new QueryParser("content", new ClassicAnalyzer());
Query result = parser.parse(searchTerm);
searchTerm = result.toString("content");

此代码将翻译serach pharse

Europe/Berlin

europe berlin

这将导致预期的文档集。

注意:这也适用于更复杂的情况。 搜索词

Europe/Berlin GSX-R1000

将被翻译成:

(europe berlin) GSX-R1000

这将使用KeyWordAnalyzer正确搜索组合中的所有短语。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM