复杂的同义词匹配

时间:2013-09-02 12:19:00

标签: regex search solr lucene synonym

我需要与Solr进行一些同义词匹配。

例如在瑞典,街道名称通常具有Foogatan的形式,其中gatan是英语街道的名称。此街道名称可以缩写为Foog.(有点像st.英文版street

我很熟悉synonyms.txt的工作方式,但我不知道如何创建一个同义词来检查它是否包含gatan之前或g.之前的一些字母。

我需要一个与*g.*gatan匹配的同义词。

我最终做到了这一点(似乎是我正在追求的粗略草案)

public boolean incrementToken() throws IOException {

    // See http://solr.pl/en/2012/05/14/developing-your-own-solr-filter/

    if (!input.incrementToken()) return false;

    String string = charTermAttr.toString();

    boolean containsGatan = string.contains("gatan");
    boolean containsG = string.contains("g.");

    if (containsGatan) {

        string = string.replace("gatan", "g.");

        char[] newBuffer = string.toCharArray();

        charTermAttr.setEmpty();
        charTermAttr.copyBuffer(newBuffer, 0, newBuffer.length);

        return true;
    }

    if (containsG) {

        string = string.replace("g.", "gatan");

        char[] newBuffer = string.toCharArray();

        charTermAttr.setEmpty();
        charTermAttr.copyBuffer(newBuffer, 0, newBuffer.length);

        return true;
    }

    return false;
}

我遇到的类似问题是您可以以031-123456031123456的形式编写电话号码。在搜索031123456等电话号码时,会找到031-123456

我如何在Solr中实现这一目标?

1 个答案:

答案 0 :(得分:0)

对于第一个,您可以编写一个自定义TokenFilter并将其连接到您的分析器中(这并不难,请查看org.apache.lucene.analysis.ASCIIFoldingFilter的一些简单示例。)

使用PatternReplaceCharFilterFactory可以解决第二个问题: http://docs.lucidworks.com/display/solr/CharFilterFactories

您必须从数字和索引中删除' - '字符/仅搜索数字。 类似的问题: Solr PatternReplaceCharFilterFactory not replacing with specified pattern

从每个令牌的末尾删除gatan的简单示例:

public class Gatanizer extends TokenFilter {

    private final CharTermAttribute termAttribute = addAttribute(CharTermAttribute.class);

    /**
     * Construct a token stream filtering the given input.
     */
    protected Gatanizer(TokenStream input) {
        super(input);
    }

    @Override
    public boolean incrementToken() throws IOException {
        if (input.incrementToken()) {

            final char[] buffer = termAttribute.buffer();
            final int length = termAttribute.length();

            String tokenString = new String(buffer, 0, length);
            tokenString = StringUtils.removeEnd(tokenString, "gatan");

            termAttribute.setEmpty();
            termAttribute.append(tokenString);

            return true;
        }

        return false;
    }

}

我已将TokenFilter注册到Solr字段:

    <fieldtype name="gatan" stored="false" indexed="false" multiValued="true" class="solr.TextField">
        <analyzer>
            <tokenizer class="solr.StandardTokenizerFactory"/>
            <filter class="solr.LowerCaseFilterFactory"/>
            <filter class="solr.ASCIIFoldingFilterFactory"/>
            <filter class="gatanizer.GatanizerFactory"/>
        </analyzer>
    </fieldtype>

您还需要一些简单的GatanizerFactory,它会返回您的Gatanizer