繁体   English   中英

Lucene中Field和StringField有什么区别?

[英]What is the difference between Field and StringField in Lucene?

我在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作为参数传递, Store.Yes对StringField建立索引,但不会对其进行分析。 但我的问题是,因为我在方法1中对Field使用setIndexed(true)setStored(true) ,为什么我没有从方法1得到类似的结果? 是因为如果我使用Field还是因为使用了TermQuery而执行了一些额外的事情? 使这两种方法不同的主要原因是什么? 请帮助我理解它们的不同之处。

谢谢!

所以这就是我在想的事情。

在第一种方法中,您使用analyzer来索引哪些小写输入令牌。

所以例如Top/Arts/Animation/Training这将存储如下

顶部/艺术/动画/培训

现在,当您使用TERMQUERY搜索它时,termquery实际上会搜索确切的字符串。 Top/Arts/Animation/Training ,由于索引中的小写,所以不匹配任何东西。

让我们谈谈第二种方法。 由于您使用了StringField,因此不会分析字段并将其按原样存储。 即您的索引在StringField案例中包含以下内容

前/艺术/动画/培训

所以现在当你使用TermQuery进行搜索时,它会匹配,因为它是按原样存储的。

在第一种方法中获得结果

使用QueryParser构建查询,而不是使用在索引时使用的相同分析器使用TermQuery

请阅读此处了解TERMQUERYQUERYPARSER之间的QUERYPARSER

Lucene 6.0中的TermQuery和QueryParser有什么区别?

编辑

存储只意味着原始字段值存储在索引中。 这样它就可以在返回搜索结果时返回。 搜索发生在索引上而不是存储的值上。 存储属性背后的原因是lucene“分析”或将输入数据转换为更有效的形式,以实现更快速和更相关的搜索(使用不同的分析器和标记器)。 不幸的是,分析的数据经常不再适合显示。 设置“stored = true”可确保以原始形式检索原始数据。

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,以获取具有与StringField相同设置的新的可修改FieldType,如下所示:

FieldType _contentFieldType = new FieldType(StringField.TYPE_STORED);

暂无
暂无

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

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