Java Lucene中Field和StringField的区别是什么?

Java Lucene中Field和StringField的区别是什么?,java,lucene,Java,Lucene,我正在lucene索引中搜索完全匹配的文档标题。为了实现这一点,我有以下两种替代方法来为将被索引的文档创建字段 方法1: FieldType _contentFieldType = new FieldType(); _contentFieldType.setIndexed(true); _contentFieldType.setStored(true); Document doc = new Document(); doc.add(new Field("content", getContent

我正在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)
,为什么我没有从方法1得到类似的结果?这是因为如果我使用Field,会执行一些额外的操作,还是因为使用TermQuery?使这两种方法不同的主要原因是什么?请帮我理解它们之间的区别


谢谢

以下是我认为正在发生的事情

在第一种方法中,您使用了一个
分析器
对小写输入标记进行索引

因此,例如
Top/Arts/Animation/Training
这将存储如下

顶级/艺术/动画/培训

现在,当您使用
TERMQUERY
搜索它时,TERMQUERY实际上是在搜索确切的字符串。i、 e
Top/Arts/Animation/Training
,由于索引中的小写字母,因此不匹配任何内容

让我们谈谈第二种方法。由于使用了StringField,因此不会对字段进行分析,而是按原样存储。i、 e您的索引在StringField案例中包含以下内容

顶级/艺术/动画/培训

现在,当您使用TermQuery进行搜索时,这将匹配,因为它是按原样存储的

在第一种方法中获得结果

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

请阅读此处了解
TERMQUERY
QUERYPARSER

编辑


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

StringField没有标记化(也就是说,它不会通过分析器运行以拆分为标记)。除非您另行指定,否则您的字段类型将默认为标记化,因此调用
setTokenized(false)
(注意:您似乎使用的是4.10版或更早版本,因此我将假设为4.10版。尽管如此,说明这一点还是很有帮助的,因为自那时以来,字段类型API发生了一些变化):

或者,您可以复制存储的
StringField.TYPE\u
FieldType,以获得一个新的可修改的FieldType,其设置与StringField相同,如下所示:

FieldType _contentFieldType = new FieldType(StringField.TYPE_STORED);

你能给出一个你试图搜索的值的例子吗?你正在使用的标记器是什么?我没有标记任何东西。因为我只有一个术语的查询。所以,没有使用标记化。您如何构建索引?你能发布你用来创建索引的分析器吗?让我们来看看。之前我是这么做的。在使用字段的文档中,我还有两个字段,但其中没有分析器的影响。所以,我只是想知道你提到的分析器的功能是否正确,那么我如何存储和索引两个不同的字段和两个不同的内容。一个是干的,另一个不是!!让我明白这一点。您是说您使用了同一个writer,该writer使用您的“特殊索引器”来索引这两个其他字段?在这两个字段中,您可以使用TERMQUERY进行搜索?所以从本质上讲,小写不会影响这些搜索?我的意思是,给定字段和存储的setStored(yes)。对于StringField,是的,它们有什么不同?他们应该是一样的,但我从他们那里得到了不同的行为。是的,字符串在索引中不是小写的,我已经检查过了。TermQuery将整个查询视为一个术语,但如果我使用QueryParser,它会将查询拆分为几个术语。为什么您认为setStored(是)和Store(存储)。是的,对索引的存储方式有任何影响?stored(存储)只意味着原始字段值存储在索引中。以便在返回搜索结果时返回。搜索发生在索引上,而不是存储值上。存储属性背后的原因是lucene“分析”或将输入数据转换为更有效的形式,以实现更快、更相关的搜索(使用不同的分析器和标记器)。不幸的是,分析的数据通常不再适合显示。设置“stored=true”可确保可以以原始形式检索原始数据。
FieldType _contentFieldType = new FieldType(StringField.TYPE_STORED);