1.
基于属性的 API 的工作原理是,每个TokenStream
在你的分析器链中以某种方式修改了某些的状态Attribute
每次通话时都会有incrementToken()
。然后链中的最后一个元素产生最终的代币。
每当分析器链的客户端调用时incrementToken()
, 最后TokenStream
会设置一些状态Attribute
s 为表示下一个标记所需的任何内容。如果无法这样做,它可能会调用incrementToken()
在其输入上,让前一个TokenStream
做好它的工作。这一直持续到最后TokenStream
回报false
,表示没有更多可用的令牌。
A captureState
复制所有的状态Attribute
召唤的sTokenStream
into a State
, a restoreState
覆盖每个Attribute
的状态与之前捕获的任何内容(作为参数给出)。
令牌过滤器的工作方式是,它会调用input.incrementToken()
,使得之前的TokenStream
将设置Attribute
s' 状态到下一个标记是什么。然后,如果您定义的条件成立(例如,termAtt 是“b”),它会将“bb”添加到堆栈中,将此状态保存在某处并返回 true,以便客户端可以使用令牌。在下一次通话时incrementToken()
,它不会使用input.incrementToken()
。无论当前状态是什么,它都代表先前已消耗的令牌。然后过滤器恢复状态,使一切都和之前一模一样,然后产生“bb”作为当前令牌并返回true,以便客户端可以消费该令牌。仅在下一次调用时,它才会(再次)消耗上一个过滤器中的下一个令牌。
这实际上不会产生您显示的图表,但插入"bb"
after "b"
,所以这确实是
(a) -> (b) -> (bb) -> (c)
那么,为什么首先要拯救国家呢?
在生产代币时,您需要确保,例如短语查询或突出显示将正常工作。当你有了文字"a b c"
and "bb"
是同义词"b"
,您会期望短语查询"b c"
去工作,以及"bb c"
。您必须告诉索引,“b”和“bb”都处于相同的位置。 Lucene 为此使用位置增量,并且默认情况下,位置增量为 1,这意味着每个新标记(读取、调用incrementToken()
) 在前一个位置之后出现 1 个位置。因此,对于最终位置,生产流是
(a:1) -> (b:2) -> (bb:3) -> (c:4)
当你真正想要的时候
(a:1) — -> (b:2) -> — (c:3)
\ /
-> (bb:2) ->
因此,为了让过滤器生成图表,您必须将插入的位置增量设置为 0"bb"
private final PositionIncrementAttribute posIncAtt = addAttribute(PositionIncrementAttribute.class);
// later in incrementToken
restoreState(savedState);
posIncAtt.setPositionIncrement(0);
termAtt.setEmpty().append(extraTokens.remove());
The restoreState
确保保留其他属性,例如偏移量、令牌类型等,并且您只需更改用例所需的属性。
是的,您正在覆盖之前的任何状态restoreState
,因此您有责任在正确的地方使用它。只要你不打电话input.incrementToken()
,您不会推进输入流,因此您可以对状态执行任何您想要的操作。
2.
词干分析器仅更改标记,它通常不会生成新标记,也不会更改位置增量或偏移量。
此外,由于位置增量意味着当前术语应该出现positionIncrement
在前一个标记之后的位置,你应该有qux
增量为 1,因为它是之后的下一个标记of
and 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 |
+--------+---------------+-----------+--------------+-----------+
作为基本规则,对于多术语同义词,其中“ABC”是“a b c”的同义词,您应该看到,
- positionIncrement("ABC") > 0(第一个标记的增量)
- positionIncrement(*) >= 0(位置不得向后移动)
- startOffset("ABC") == startOffset("a") and endOffset("ABC") == endOffset("c")
- 实际上,相同(开始|结束)位置的标记必须具有相同的(开始|结束)偏移量
希望这有助于阐明一些问题。