Joh*_*erg 11 java lucene solr token solr4
我写了一个TokenFilter在流中添加令牌的.
如果有人能够阐明语义,我将不胜感激.特别是在(*)恢复状态时,这是否意味着我们要么覆盖当前令牌,要么在捕获状态之前创建令牌?
这大致就是我所做的
private final LinkedList<String> extraTokens = new LinkedList<String>();
private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
private State savedState;
@Override
public boolean incrementToken() throws IOException {
if (!extraTokens.isEmpty()) {
// Do we not loose/overwrite the current termAtt token here? (*)
restoreState(savedState);
termAtt.setEmpty().append(extraTokens.remove());
return true;
}
if (input.incrementToken()) {
if (/* condition */) {
extraTokens.add("fo");
savedState = captureState();
}
return true;
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
这是否意味着,对于空白标记化字符串的输入流 "a b c"
(a) -> (b) -> (c) -> ...
Run Code Online (Sandbox Code Playgroud)
在哪里bb使用新的同义词b,使用时图形将如此构造restoreState?
(a)
/ \
(b) (bb)
\ /
(c)
|
...
Run Code Online (Sandbox Code Playgroud)
鉴于文本foo bar baz与fo存在的茎foo和qux是同义词bar baz,都我构建了正确的属性表?
+--------+---------------+-----------+--------------+-----------+
| Term | startOffset | endOffset | posIncrement | posLenght |
+--------+---------------+-----------+--------------+-----------+
| foo | 0 | 3 | 1 | 1 |
| fo | 0 | 3 | 0 | 1 |
| qux | 4 | 11 | 0 | 2 |
| bar | 4 | 7 | 1 | 1 |
| baz | 8 | 11 | 1 | 1 |
+--------+---------------+-----------+--------------+-----------+
Run Code Online (Sandbox Code Playgroud)
knu*_*ker 21
1.
基于属性的API如何工作,TokenStream分析器链中的每一个都以某种方式修改了Attribute每次调用时某些s 的状态incrementToken().链中的最后一个元素然后生成最终的标记.
每当分析器链的客户端调用时incrementToken(),最后一个TokenStream会将某些Attributes 的状态设置为表示下一个令牌所需的任何内容.如果它不能这样做,它可以调用incrementToken()它的输入,让以前TokenStream做它的工作.这一直持续到最后一次TokenStream返回false,表明没有更多令牌可用.
A captureState将所有Attribute调用的状态复制TokenStream到a中State,用之前捕获的任何内容restoreState覆盖每个Attribute状态(作为参数给出).
您的令牌过滤器的工作方式是,它将调用input.incrementToken(),以便前一个TokenStream将Attributes'状态设置为下一个令牌.然后,如果您定义的条件成立(例如,termAtt是"b"),它会将"bb"添加到堆栈,将此状态保存在某处并返回true,以便客户端可以使用该令牌.在下次调用时incrementToken(),它不会使用input.incrementToken().无论当前状态如何,它都代表先前已经消耗的令牌.然后,过滤器恢复状态,以便一切都与之前完全一样,然后生成"bb"作为当前令牌并返回true,以便客户端可以使用令牌.只有在下次调用时,它才会(再次)使用前一个过滤器中的下一个标记.
这实际上不会产生你显示的图形,而是插入"bb"后"b",所以它确实如此
(a) -> (b) -> (bb) -> (c)
Run Code Online (Sandbox Code Playgroud)
那么,你为什么要首先拯救国家?在生成令牌时,您需要确保,例如短语查询或突出显示将正常工作.如果您有文本"a b c"并且"bb"是同义词"b",那么您希望短语查询"b c"能够正常工作,以及"bb c".你必须告诉索引,"b"和"bb"都处于相同的位置.Lucene使用位置增量,默认情况下,位置增量为1,这意味着每个新标记(读取,调用incrementToken())在前一个标记之后的1个位置.因此,对于最终位置,产生流是
(a:1) -> (b:2) -> (bb:3) -> (c:4)
Run Code Online (Sandbox Code Playgroud)
而你真的想要
(a:1) — -> (b:2) -> — (c:3)
\ /
-> (bb:2) ->
Run Code Online (Sandbox Code Playgroud)
因此,对于生成图形的过滤器,必须将插入的位置增量设置为0 "bb"
private final PositionIncrementAttribute posIncAtt = addAttribute(PositionIncrementAttribute.class);
// later in incrementToken
restoreState(savedState);
posIncAtt.setPositionIncrement(0);
termAtt.setEmpty().append(extraTokens.remove());
Run Code Online (Sandbox Code Playgroud)
在restoreState确保,其他属性,如偏移,令牌类型等被保存,你只需要改变的,所需要的您的使用案例.是的,你要覆盖以前的状态restoreState,所以你有责任在正确的地方使用它.只要你不打电话input.incrementToken(),你就不会推进输入流,所以你可以用状态做任何你想做的事情.
2.
词干分析器仅更改令牌,它通常不会生成新令牌,也不会更改位置增量或偏移量.此外,由于位置增量意味着当前术语应该positionIncrement位于前一个令牌之后的位置qux,因此它应该具有增量1,因为它是之后的下一个令牌of并且bar应该具有0的增量,因为它处于相同的位置作为qux.表格看起来很像
+--------+---------------+-----------+--------------+-----------+
| Term | startOffset | endOffset | posIncrement | posLenght |
+--------+---------------+-----------+--------------+-----------+
| fo | 0 | 3 | 1 | 1 |
| qux | 4 | 11 | 1 | 2 |
| bar | 4 | 7 | 0 | 1 |
| baz | 8 | 11 | 1 | 1 |
+--------+---------------+-----------+--------------+-----------+
Run Code Online (Sandbox Code Playgroud)
作为一个基本规则,对于多项同义词,"ABC"是"ab c"的同义词,你应该看到,
希望这有助于揭示一些亮点.