Lucene停止短语过滤器

Lucene停止短语过滤器,lucene,Lucene,我正试图为Lucene编写一个过滤器,类似于StopWordsFilter(从而实现TokenFilter),但我需要删除短语(标记序列)而不是单词 “停止短语”本身表示为一系列标记:不考虑标点符号 我认为我需要对令牌流中的令牌进行某种缓冲,当匹配完整短语时,我丢弃缓冲区中的所有令牌 考虑到Lucene的TokenStream这样的词流,实现“停止短语”过滤器的最佳方法是什么?我认为,你真的必须编写自己的分析器,因为某些词序列是否是“短语”取决于提示,例如标点符号,标记化后不可用。我得到了一个解

我正试图为Lucene编写一个过滤器,类似于StopWordsFilter(从而实现TokenFilter),但我需要删除短语(标记序列)而不是单词

“停止短语”本身表示为一系列标记:不考虑标点符号

我认为我需要对令牌流中的令牌进行某种缓冲,当匹配完整短语时,我丢弃缓冲区中的所有令牌


考虑到Lucene的TokenStream这样的词流,实现“停止短语”过滤器的最佳方法是什么?

我认为,你真的必须编写自己的分析器,因为某些词序列是否是“短语”取决于提示,例如标点符号,标记化后不可用。

我得到了一个解决方案:使用Lucene的CachingTokenFilter作为起点:

这个解决方案实际上是正确的

编辑:我修复了死链接。这是这条线索的记录

我的问题:

我正在尝试用新的令牌流实现一个“停止短语过滤器” API

我想能够窥视N个令牌,看看当前 令牌+N个后续令牌与“停止短语”(停止短语的集合)匹配 保存在哈希集中),然后在这些令牌与 停止短语,或者如果它们不匹配,则全部保留

为此,我希望使用captureState()和restoreState() 返回到流的起点

我尝试了这些API的多种组合。我最后一次尝试是在代码中 下面,这不起作用

    static private HashSet<String> m_stop_phrases = new HashSet<String>(); 
    static private int m_max_stop_phrase_length = 0; 
... 
    public final boolean incrementToken() throws IOException { 
        if (!input.incrementToken()) 
            return false; 
        Stack<State> stateStack = new Stack<State>(); 
        StringBuilder match_string_builder = new StringBuilder(); 
        int skippedPositions = 0; 
        boolean is_next_token = true; 
        while (is_next_token && match_string_builder.length() < m_max_stop_phrase_length) { 
            if (match_string_builder.length() > 0) 
                match_string_builder.append(" "); 
            match_string_builder.append(termAtt.term()); 
            skippedPositions += posIncrAtt.getPositionIncrement(); 
            stateStack.push(captureState()); 
            is_next_token = input.incrementToken(); 
            if (m_stop_phrases.contains(match_string_builder.toString())) { 
              // Stop phrase is found: skip the number of tokens 
              // without restoring the state 
              posIncrAtt.setPositionIncrement(posIncrAtt.getPositionIncrement() + skippedPositions); 
              return is_next_token; 
            } 
        } 
        // No stop phrase found: restore the stream 
        while (!stateStack.empty()) 
            restoreState(stateStack.pop()); 
        return true; 
    } 
static private HashSet m_stop_phrases=new HashSet();
静态私有int m_max_stop_短语长度=0;
... 
public final boolean incrementToken()引发IOException{
如果(!input.incrementToken())
返回false;
Stack stateStack=新堆栈();
StringBuilder match_string_builder=新StringBuilder();
int skippedPositions=0;
布尔值为_next_token=true;
while(是下一个标记和匹配字符串生成器.length()0)
匹配字符串生成器。追加(“”);
匹配字符串生成器.append(termAtt.term());
skippedPositions+=posIncrAtt.getPositionIncrement();
stateStack.push(captureState());
is_next_token=input.incrementToken();
如果(m_stop_phrases.contains(match_string_builder.toString()){
//找到停止短语:跳过令牌数
//不恢复国家
posIncrAtt.setPositionIncrement(posIncrAtt.getPositionIncrement()+skippedPositions);
返回是下一个令牌;
} 
} 
//未找到停止短语:还原流
而(!stateStack.empty())
restoreState(stateStack.pop());
返回true;
} 
哪一个是我实施“停止”的正确方向 短语“过滤器

正确答案:

restoreState仅恢复令牌内容,而不恢复整个流。所以 您无法回滚令牌流(这在 旧API)。代码末尾的while循环无法正常工作 因为这一点,我们必须谨慎。您可以使用可以重置的CachingTokenFilter
再次消费,作为进一步工作的来源

实际上,标点符号可以被丢弃:我需要匹配那些本身可以被描述为单词标记的短语,这就是链接答案不好的原因。链接现在已失效。@Mystion修复了失效链接,并报告了线程内容的副本,以避免将来出现链接问题。