Lucene停止短语过滤器
我正试图为Lucene编写一个过滤器,类似于StopWordsFilter(从而实现TokenFilter),但我需要删除短语(标记序列)而不是单词 “停止短语”本身表示为一系列标记:不考虑标点符号 我认为我需要对令牌流中的令牌进行某种缓冲,当匹配完整短语时,我丢弃缓冲区中的所有令牌Lucene停止短语过滤器,lucene,Lucene,我正试图为Lucene编写一个过滤器,类似于StopWordsFilter(从而实现TokenFilter),但我需要删除短语(标记序列)而不是单词 “停止短语”本身表示为一系列标记:不考虑标点符号 我认为我需要对令牌流中的令牌进行某种缓冲,当匹配完整短语时,我丢弃缓冲区中的所有令牌 考虑到Lucene的TokenStream这样的词流,实现“停止短语”过滤器的最佳方法是什么?我认为,你真的必须编写自己的分析器,因为某些词序列是否是“短语”取决于提示,例如标点符号,标记化后不可用。我得到了一个解
考虑到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修复了失效链接,并报告了线程内容的副本,以避免将来出现链接问题。