Solr自定义过滤器TokenStream问题

时间:2014-12-05 10:36:29

标签: solr lucene

对于索引和查询,我需要执行下面列出的某些转换。因此我写了一个自定义过滤器。如何执行令牌的连接,并将其传递给NGramFilterFactory过滤器。请告诉我代码中需要改进的地方。

这是schema.xml文件中的配置:

<tokenizer class="solr.WhitespaceTokenizerFactory"/>

    <filter class="solr.LowerCaseFilterFactory" />
    <filter class="solr.TrimFilterFactory" />
    <filter class="solr.TrimFilterFactory" pattern="([^a-z])" replacement="" replace="all" />
    <filter class="solr.StopFilterFactory" ignoreCase="true" words="custom_stop_words.txt"/>
    <filter class="intuit.ripple.solr.ConcatFilterFactory" />
    <filter class="solr.NGramFilterFactory" minGramSize="3" maxGramSize="3" />

以下是我要解决的用例示例:

1. Input value: "foo Bar Baz qux"
2. WhitespaceTokenizerFactory: "foo", "Bar", "Baz", "qux"
3. LowerCaseFilterFactory: "foo", "bar", "baz", "qux"
4. TrimFilterFactory, TrimFilterFactory and StopFilterFactory have nothing to do in this case.
5. ConcatFilterFactory: "foobarbazqux". It should concatenate the tokens.
6. NGramFilterFactory: This will generate the token.

以下是来自ConcatFilter的incrementToken()方法:

@Override
public boolean incrementToken()  throws IOException  {

    StringBuilder builder = new StringBuilder();

    while (input.incrementToken()) {
        int len = charTermAtt.length();
        char buffer[] = charTermAtt.buffer();
        builder.append(buffer, 0, len);
        System.out.println("Tokens: " + new String(buffer, 0, len));
        clearAttributes();
        charTermAtt.setEmpty();
    }
    System.out.println("Concat tokens: " + builder.toString());

    charTermAtt.copyBuffer(builder.toString().toCharArray(), 0, builder.length());
    charTermAtt.setLength(builder.length());
    posIncAtt.setPositionIncrement(1);
    setOffsetAttr.setOffset(0, builder.length());

    input.end();
    input.close();
    return false;
}

这里我使用while循环来获取所有令牌并将它们连接在一起。有没有办法在不循环的情况下一次获取所有令牌?

2 个答案:

答案 0 :(得分:0)

我认为你想要做的事情比你实施的更多:D

您在incrementToken方法中所做的只是遍历整个输入(在本例中是StopFilter的输出)。在每次增量令牌调用中,您应该从输入中获取单个(或更多,如果需要)令牌,并生成SINGLE令牌以输出。

所以我猜你不想在这里使用“while”循环,而且在每次交互中调用“clearAttributes()”。

我猜也猜你这样:

Tokens: foo
Tokens: bar
Concat tokens: foo bar

但实际上从两个令牌“foo”和“bar”中你制作了单个令牌“foo bar”,我猜这不是你的意图。请描述您的ConcatFilterFactory应该做什么。目前,它只将多个令牌合并为单个令牌。

您在此处有一个关于TokenFilter的讨论示例:http://search-lucene.com/m/ukJmjphJte/tokenfilter&subj=custom+TokenFilter。您可以使用此搜索框查找有关Solr / Lucene相关信息的更多信息:http://search-lucene.com/

答案 1 :(得分:0)

我认为无法一次获取所有令牌,您需要像在代码中一样进行循环。但你可以使用不同的方法。而不是使用solr.WhitespaceTokenizerFactory使用solr.KeywordTokenizerFactoryKeywordTokenizerFactory只在令牌流中放入一个精确输入值的标记。然后在ConcatFilter中,您只需从令牌流中获取第一个也是唯一的令牌,并将其中的所有空格替换为空字符串。在这种情况下,您需要在StopFilter之后添加NGramFilter。使用您的示例,您将拥有:

1. Input value: "foo Bar Baz qux"
2. KeywordTokenizerFactory: "foo Bar Baz qux"
3. LowerCaseFilterFactory: "foo bar baz qux"
4. ConcatFilterFactory: "foobarbazqux".
5. NGramFilterFactory: This will generate the token.
6. StopFilterFactory cuts all unwanted tokens.