Lucene 4.1忽略了FieldType.tokenized = false

时间:2013-03-01 16:10:38

标签: java lucene

我正在使用Lucene 4.1来索引关键字/值对,其中关键字和值不是真实的单词 - 即,它们是不应被分析或标记化的电压,设置。例如$ P14R / 16777216.(这是任何Flow Cytometrists的FCS数据)

对于索引,我创建了一个IndexType = true,stored = true和 tokenized = false 的FieldType。这些模仿来自Lucene 1的古代Field.Keyword,我有这本书。 :-)我甚至冻结了fieldType。

我在调试器中看到了这些值。我创建了文档和索引。

当我阅读索引和文档并查看调试器中的Fields时,我会看到所有字段。名称和fieldsData看起来正确。但是,FieldType是错误的。它显示indexed = true,stored = true和 tokenized = true 。结果是我的搜索(使用TermQuery)不起作用。

我该如何解决这个问题?感谢。

P.S。我在IndexWriterConfig中使用KeywordAnalyzer。我稍后会尝试发布一些演示代码,但这是我今天真正的工作。 : - )

演示代码:

public class LuceneDemo {

  public static void main(String[] args) throws IOException {
    Directory lDir = new RAMDirectory();
    Analyzer analyzer = new KeywordAnalyzer();
    IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_41, analyzer);
    iwc.setOpenMode(OpenMode.CREATE);
    IndexWriter writer = new IndexWriter(lDir, iwc);

    // BTW, Lucene, anyway you could make this even more tedious???
    // ever heard of builders, Enums, or even old fashioned bits?
    FieldType keywordFieldType = new FieldType();
    keywordFieldType.setStored(true);
    keywordFieldType.setIndexed(true);
    keywordFieldType.setTokenized(false);

    Document doc = new Document();
    doc.add(new Field("$foo",  "$bar123", keywordFieldType));
    doc.add(new Field("contents",  "$foo=$bar123", keywordFieldType));
    doc.add(new Field("$foo2",  "$bar12345", keywordFieldType));

    Field onCreation = new Field("contents",  "$foo2=$bar12345", keywordFieldType);
    doc.add(onCreation);
    System.out.println("When creating, the field's tokenized is " + onCreation.fieldType().tokenized());
    writer.addDocument(doc);
    writer.close();

    IndexReader reader = DirectoryReader.open(lDir);
    Document d1 = reader.document(0);
    Field readBackField = (Field) d1.getFields().get(0);
    System.out.println("When read back the field's tokenized is " + readBackField.fieldType().tokenized());

    IndexSearcher searcher = new IndexSearcher(reader);

// exact match works
Term term = new Term("$foo", "$bar123" );
    Query query = new TermQuery(term);
    TopDocs results = searcher.search(query, 10);
    System.out.println("when searching for : " + query.toString() + "  hits = " + results.totalHits);

    // partial match fails
    term = new Term("$foo", "123" );
    query = new TermQuery(term);
    results = searcher.search(query, 10);
    System.out.println("when searching for : " + query.toString() + "  hits = " + results.totalHits);

    // wildcard search works
    term = new Term("contents", "*$bar12345" );
    query = new WildcardQuery(term);
    results = searcher.search(query, 10);
    System.out.println("when searching for : " + query.toString() + "  hits = " + results.totalHits);
    }
}

输出将是:

When creating, the field's tokenized is false
When read back the field's tokenized is true
when searching for : $foo:$bar123  hits = 1
when searching for : $foo:123  hits = 0
when searching for : contents:*$bar12345  hits = 1

3 个答案:

答案 0 :(得分:0)

您可以尝试将KeywordAnalyzer用于您不想标记的字段。

如果您需要多个分析器(即,如果您有其他需要标记化的字段),PerFieldAnalyzerWrapper就是这样。

答案 1 :(得分:0)

演示代码证明,当您阅读它时,tokenized的值会有所不同。不确定这是不是一个错误。

但这并不是部分搜索不起作用的原因。部分搜索不起作用,因为Lucene不进行部分搜索(除非您使用通配符),例如Says so here in StackOverflow

我一直在使用谷歌,我想我不明白。 : - )

答案 2 :(得分:0)

Lucene以小写存储所有令牌 - 因此,您需要先将搜索字符串转换为小写字母,以用于非标记化字段。