我在lucene索引中搜索完全匹配的文档标题。为了实现这一点,我有以下两种替代方法来为将要编制索引的文档创建字段。
方法1:
FieldType _contentFieldType = new FieldType();
_contentFieldType.setIndexed(true);
_contentFieldType.setStored(true);
Document doc = new Document();
doc.add(new Field("content", getContent(), _contentFieldType));
writer.addDocument(doc);
方法2:
Document doc = new Document();
doc.add(new StringField("content", getContent(), Store.YES));
writer.addDocument(doc);
然后我使用TermQuery
创建查询并在lucene索引中搜索,但如果我使用第一种方法,则不会得到任何结果。第二个适用对我来说很好。
Query query = new TermQuery(new Term(searchQuery.fields().get(0), searchQuery.queryText()));
indexSearcher.search(query, Math.max(1, collector.getTotalHits()));
文档标题示例:文档标题实际上是文档的主题,是主题的分层路径。
Top/Arts/Animation/Audio
Top/Arts/Animation/Collectibles
Top/Arts/Animation/Stop-Motion
Top/Arts/Animation/Festivals
Top/Arts/Animation/News_and_Media
Top/Arts/Animation/Chats_and_Forums
Top/Arts/Animation/Training
Top/Arts/Animation/Voice_Actors
Top/Arts/Animation/Artists
说,我想搜索Top/Arts/Animation/Training
。我需要精确的字符串匹配,所以我使用了TermQuery
。
我阅读了文档并了解了Field和StringField。因此,如果将Store.Yes
作为参数传递,则会对StringField编制索引,但不进行分析。但我的问题是,因为我在方法1中同时使用setIndexed(true)
和setStored(true)
作为Field
,为什么我没有从方法1得到类似的结果?是因为如果我使用Field还是因为使用了TermQuery而执行了一些额外的事情?使这两种方法不同的主要原因是什么?请帮助我理解它们之间的区别。
谢谢!
答案 0 :(得分:2)
所以这就是我在想的事情。
您使用analyzer
索引在第一种方法中输入令牌的小写字母。
所以例如Top/Arts/Animation/Training
这将存储如下
顶部/艺术/动画/训练
现在,当您使用TERMQUERY
进行搜索时,termquery实际上会搜索确切的字符串。即Top/Arts/Animation/Training
由于索引中的小写而无法匹配任何内容。
让我们谈谈第二种方法。由于您使用了StringField,因此不会分析字段并将其按原样存储。即你的索引在StringField案例中包含以下内容
顶/艺术/动画/训练
所以现在当你使用TermQuery进行搜索时,它将匹配,因为它按原样存储。
以第一种方法获得结果
使用QueryParser
构建查询,而不是使用TermQuery
使用在索引编制时使用的相同分析器。
请在此处阅读TERMQUERY
和QUERYPARSER
what is the difference between TermQuery and QueryParser in Lucene 6.0?
修改强>
存储只是意味着原始字段值存储在索引中。这样它就可以在返回搜索结果时返回。搜索发生在索引上而不是存储的值上。存储属性背后的原因是lucene“分析”或将输入数据转换为更有效的形式,以实现更快速和更相关的搜索(使用不同的分析器和标记器)。不幸的是,分析的数据经常不再适合显示。设置“stored = true”可确保以原始形式检索原始数据。
答案 1 :(得分:0)
StringField没有被标记化(也就是说,它不会通过分析器运行而被分割成标记)。除非另外指定,否则您的FieldType将默认为标记化,因此请调用setTokenized(false)
(注意:您似乎使用的是版本4.10或更早版本,因此我将假设为4.10。但是,由于FieldType API,因此说明这一点很有帮助。从那时起有所改变):
FieldType _contentFieldType = new FieldType();
_contentFieldType.setIndexed(true);
_contentFieldType.setStored(true);
_contentFieldType.setTokenized(false);
或者,你可以复制StringField.TYPE_STORED
FieldType,以获得一个新的可修改的FieldType,其设置与StringField的设置相同,如下所示:
FieldType _contentFieldType = new FieldType(StringField.TYPE_STORED);