2

我正在向 Solr 添加一个文本词形还原器。我必须处理整个文本,因为词形还原中的上下文很重要。

我在互联网上得到了这段代码,我做了一些修改

http://grokbase.com/t/lucene/solr-user/138d0qn4v0/issue-with-custom-tokenizer

我添加了我们的 lemmatizer 并更改了这一行

endOffset = word.length();

为了这

endOffset = startOffset + word.length();

现在,如果我使用 Solr Admin analisys,索引或查询值没有问题。我写了这个短语,当我分析值时,结果是文本很好地进行了词形还原。

问题是当我在 Query 部分进行查询和索引文档时。检查调试查询我可以看到这一点。如果我在“naiz_body”中询问“korrikan”文本(意思是“正在运行”),则该文本已得到很好的词形还原。

<str name="rawquerystring">naiz_body:"korrikan"</str>
<str name="querystring">naiz_body:"korrikan"</str>
<str name="parsedquery">naiz_body:korrika</str>
<str name="parsedquery_toString">naiz_body:korrika</str>

现在,如果此刻我要求“jolasten”文本(意思是“正在播放”),则文本不会词形化,并且 parsedquery 和 parsedquery_toString 不会更改。

<str name="rawquerystring">naiz_body:"jolasten"</str>
<str name="querystring">naiz_body:"jolasten"</str>
<str name="parsedquery">naiz_body:korrika</str>
<str name="parsedquery_toString">naiz_body:korrika</str>

如果我稍等片刻(或者如果我停止 solr 并运行它)并要求输入“jolasten”文本,我会得到很好的词形还原

<str name="rawquerystring">naiz_body:"jolasten"</str>
<str name="querystring">naiz_body:"jolasten"</str>
<str name="parsedquery">naiz_body:jolastu</str>
<str name="parsedquery_toString">naiz_body:jolastu</str>

为什么?

这是代码:

package eu.solr.analysis;

import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;

import eu.solr.analysis.Lemmatizer;

import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.analysis.Token;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;

public class LemmatizerTokenizer extends Tokenizer {
    private Lemmatizer lemmatizer = new Lemmatizer();
    private List<Token> tokenList = new ArrayList<Token>();
    int tokenCounter = -1;

    private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
    private final OffsetAttribute offsetAttribute = (OffsetAttribute)addAttribute(OffsetAttribute.class);
    private final PositionIncrementAttribute position = (PositionIncrementAttribute)addAttribute(PositionIncrementAttribute.class);

    public LemmatizerTokenizer(AttributeFactory factory, Reader reader) {
        super(factory, reader);
        System.out.println("### Lemmatizer Tokenizer ###");
        String textToProcess = null;
        try {
            textToProcess = readFully(reader);
            processText(textToProcess);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public String readFully(Reader reader) throws IOException {
        char[] arr = new char[8 * 1024]; // 8K at a time
        StringBuffer buf = new StringBuffer();
        int numChars;
        while ((numChars = reader.read(arr, 0, arr.length)) > 0) {
            buf.append(arr, 0, numChars);
        }
        System.out.println("### Read Fully ### => " + buf.toString());
        return lemmatizer.getLemma(buf.toString());
    }

    public void processText(String textToProcess) {
        System.out.println("### Process Text ### => " + textToProcess);
        String wordsList[] = textToProcess.split(" ");
        int startOffset = 0, endOffset = 0;
        for (String word : wordsList) {
            endOffset = startOffset + word.length();
            Token aToken = new Token(word, startOffset, endOffset);
            aToken.setPositionIncrement(1);
            tokenList.add(aToken);
            startOffset = endOffset + 1;
        }
    }

    @Override
    public boolean incrementToken() throws IOException {
        clearAttributes();
        tokenCounter++;
        System.out.println("### Increment Token ###");
        System.out.println("Token Counter => " + tokenCounter);
        System.out.println("TokenList size => " + tokenList.size());
        if (tokenCounter < tokenList.size()) {
            Token aToken = tokenList.get(tokenCounter);
            System.out.println("Increment Token => " + aToken.toString());
            termAtt.append(aToken);
            termAtt.setLength(aToken.length());
            offsetAttribute.setOffset(correctOffset(aToken.startOffset()),
            correctOffset(aToken.endOffset()));
            position.setPositionIncrement(aToken.getPositionIncrement());
            return true;
        }
        return false;
    }

    @Override
    public void close() throws IOException {
        System.out.println("### Close ###");
        super.close();
    }

    @Override
    public void end() throws IOException {
        // setting final offset
        System.out.println("### End ###");
        super.end();
    }

    @Override
    public void reset() throws IOException {
        System.out.println("### Reset ###");
        tokenCounter = -1;
        super.reset();
    }
}

谢谢你们!

编辑:

回答@alexandre-rafalovitch Admin UI 中的分析屏幕运行良好。如果我进行查询或索引文本,则文本会很好地进行词形还原。问题出在查询 UI 中。如果我首先调用 lemmatizer 进行查询,但第二个看起来像使用缓冲的第一个 lemmatized 文本并直接调用 incrementToken。当我进行此查询时,请参阅代码输出:在分析 UI 中,如果我查询 Korrikan 然后查询 Jolasten 它输出以下内容:

## BasqueLemmatizerTokenizer create
### BasqueLemmatizer Tokenizer ###
### Read Fully ### => korrikan
### Eustagger OUT ### => korrika  
### Process Text ### => korrika  
### Reset ###
### Increment Token ###
Token Counter => 0
TokenList size => 1
Increment Token => korrika
### Increment Token ###
Token Counter => 1
TokenList size => 1

## BasqueLemmatizerTokenizer create
### BasqueLemmatizer Tokenizer ###
### Read Fully ### => Jolasten
### Eustagger OUT ### => jolastu  
### Process Text ### => jolastu  
### Reset ###
### Increment Token ###
Token Counter => 0
TokenList size => 1
Increment Token => jolastu
### Increment Token ###
Token Counter => 1
TokenList size => 1

如果我在 Query UI 上进行此查询,它会输出以下内容:

## BasqueLemmatizerTokenizer create
### BasqueLemmatizer Tokenizer ###
### Read Fully ### => korrikan
### Eustagger OUT ### => korrika  
### Process Text ### => korrika  
### Reset ###
### Increment Token ###
Token Counter => 0
TokenList size => 1
Increment Token => korrika
### Increment Token ###
Token Counter => 1
TokenList size => 1
### End ###
### Close ###

### Reset ###
### Increment Token ###
Token Counter => 0
TokenList size => 1
Increment Token => korrika
### Increment Token ###
Token Counter => 1
TokenList size => 1
### End ###
### Close ###

在第二个中,它没有创建标记器,看起来像是重置了它,但它读取了旧文本。

我写信给代码所有者,他回复我查看 TrieTokenizer。

4

2 回答 2

0

你确定问题是 lematizer 吗?您可以通过在管理 UI 的分析屏幕中输入文本来检查它。输入文本并查看分析器链的作用。

但是,以下部分:

如果我稍等片刻(或者如果我停止 solr 并运行它)并要求输入“jolasten”文本,我会得到很好的词形还原

让我觉得也许你只是忘记提交你的索引文本。然后,在您的 solrconfig.xml 中配置的时间间隔的软提交将解释内容显示之前的延迟。

于 2014-09-03T19:59:00.937 回答
0

最后我做到了!

我修改了 PatternTokenizer,然后我使用 StandardTokenizer 来使用 lemmatizer。简而言之,我对输入中的字符串进行词形还原,然后使用词形化文本创建一个 StringReader。

这是代码,希望它对某人有用(修改 StandardTokenizer 脚本):

...

public String processReader(Reader reader) throws IOException {
    char[] arr = new char[8 * 1024]; // 8K at a time
    StringBuffer buf = new StringBuffer();
    int numChars;
    while ((numChars = reader.read(arr, 0, arr.length)) > 0) {
        buf.append(arr, 0, numChars);
    }
    return lemmatizer.getLemma(buf.toString());
}

...

public void reset() throws IOException {
    scanner.yyreset(new StringReader(processReader(input)));
}
于 2014-09-08T11:38:59.960 回答