将令牌添加到 lucene 令牌流

2023-12-25

我写了一个TokenFilter它在流中添加令牌。

1.测试表明它有效,但我不完全明白为什么。

如果有人能阐明语义,我将不胜感激。特别是,在(*),恢复状态,是不是意味着我们要么覆盖当前的token,要么覆盖捕获状态之前创建的token?

这大致就是我所做的

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;
}

这是否意味着,对于空白标记化字符串的输入流"a b c"

 (a) -> (b) -> (c) -> ...

where bb是一个新的同义词b,当restoreState用来?

    (a)
   /   \
(b)    (bb)
   \   /
    (c)
     |
    ...

2. 属性

鉴于文本foo bar baz with fo是...的茎foo and 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     |
+--------+---------------+-----------+--------------+-----------+

1.

基于属性的 API 的工作原理是,每个TokenStream在你的分析器链中以某种方式修改了某些的状态Attribute每次通话时都会有incrementToken()。然后链中的最后一个元素产生最终的代币。

每当分析器链的客户端调用时incrementToken(), 最后TokenStream会设置一些状态Attributes 为表示下一个标记所需的任何内容。如果无法这样做,它可能会调用incrementToken()在其输入上,让前一个TokenStream做好它的工作。这一直持续到最后TokenStream回报false,表示没有更多可用的令牌。

A captureState复制所有的状态Attribute召唤的sTokenStream into a State, a restoreState覆盖每个Attribute的状态与之前捕获的任何内容(作为参数给出)。

令牌过滤器的工作方式是,它会调用input.incrementToken(),使得之前的TokenStream将设置Attributes' 状态到下一个标记是什么。然后,如果您定义的条件成立(例如,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")
    • 实际上,相同(开始|结束)位置的标记必须具有相同的(开始|结束)偏移量

希望这有助于阐明一些问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将令牌添加到 lucene 令牌流 的相关文章

  • JAVA - 带有特殊字符的 LDAP 密码不起作用

    我试图在我的系统上创建一个登录屏幕 在 Active Directory 中进行查询 但是当用户的密码包含一些特殊字符 如 和 时 它不会验证 我需要加密密码才能工作吗 我该怎么做 我使用 getPassword 通过 JPasswordF
  • .java 和 .scala 类之间是否可能存在循环依赖?

    假设我在 java 文件中定义了类 A 在 scala 文件中定义了类 B A 类使用 B 类 B 类使用 A 类 如果我使用 java 编译器 则会出现编译错误 因为 B 类尚未编译 如果我使用scala编译器A类将找不到 有没有可以同时
  • Spring webflow 应用程序:HTTP 302 暂时移动

    我的 java 应用程序中的每个请求都会生成另外 2 个带有 HTTP 302 错误的请求 例如 如果请求查看名为板 html 这个请求是从首页 html 我收到按以下顺序生成的 3 个请求 POST home html 302 Moved
  • Java/JAXB:将具有相同名称但不同属性值的 XML 元素解组到不同的类成员

    我正在尝试根据其属性之一将具有多个 Fields 元素的 XML 解析为不同的类成员 这是 XML
  • 使用多个构造函数创建不可变类

    我正在阅读这一页 https docs oracle com javase tutorial essential concurrency imstrat html关于在 Java 中创建不可变类 并决定根据页面上概述的规范修改我正在编写的类
  • 使用 Java 编程式 HTML 文档生成

    有谁知道如何在 Java 中以编程方式生成 HTMLDocument 对象 而不需要在外部生成字符串 然后使用 HTMLEditorKit read 来解析它 我问的两个原因 首先 我的 HTML 生成例程需要非常快 并且我认为将字符串解析
  • 删除 servlet 中的 cookie 时出现问题

    我尝试使用以下代码删除 servlet 中的 cookie Cookie minIdCookie null for Cookie c req getCookies if c getName equals iPlanetDirectoryPr
  • 如何在具有动态列的表中插入值 Jdbc/Mysql

    我想在具有动态列的表中添加值 我设法创建一个包含动态列的表 但我不知道如何插入数据 Create Table sql CREATE TABLE MyDB myTable level INTEGER 255 int columnNumber
  • 如何消除警告:使用“$”而不是“.”对于 Eclipse 中的内部类

    我是 Android 开发新手 当我将 eclipse 和 Android SDK 更新到最新版本后 我收到警告 Use instead of for inner classes or use only lowercase letters
  • JSP 标签+ scriptlet。如何启用脚本?

    我有一个使用标签模板的页面 我的 web xml 非常基本 我只是想在页面中运行一些代码 不 我对标签或其他替代品不感兴趣 我想使用不好的做法 scriptlet 哈哈 到目前为止 我收到了 HTTP ERROR 500 错误 Script
  • java JFileChooser 文件大小过滤器

    我知道我可以按文件类型进行过滤 但是可以按文件大小进行过滤吗 例如 JFileChooser 仅显示 3 MB 以内的图片 简短的回答应该是 你尝试过什么 长答案是肯定的 JFileChooser fc new JFileChooser f
  • Java G1 GC 处理引用对象运行缓慢

    我已经在 J ava 上运行了计数器 它24小时工作 每秒点击通过100次左右 白天 GC 处理时间从 20 60 毫秒缓慢上升到 10000 60000 毫秒 然后下降到 20 60 毫秒 这种模式不时地重复 从 GC 日志中我发现 GC
  • 哪种 Java DOM 包装器是最好或最受欢迎的? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何计算文件中单词的长度?爪哇

    我正在尝试编写一个代码来计算文件中特定长度的单词数 例如 How are you 会打印 Proportion of 3 letter words 100 3 words 我想计算长度为 1 2 3 4 5 6 7 8 9 10 11 12
  • Mule/码头设置

    我有一个正在运行的 Mule 应用程序 我想在其上设置 Jetty 来响应 http 请求 以下配置
  • 使用 Maven 3 时 Cobertura 代码覆盖率为 0%

    读完这篇文章后 将 Cobertura 与 Maven 3 0 2 一起使用的正确方法是什么 https stackoverflow com questions 6931360 what is the proper way to use c
  • JDK 7 的快速调试/调试构建

    我正在寻找 JDK 的调试 或者我猜他们称之为快速调试构建 以启用在运行时生成的打印程序集以及查找性能问题时所需的其他诊断 就目前情况而言 我似乎找不到可以直接使用的 现成的 快速调试构建二进制包 有人可以帮我提供下载链接 或者至少提供有关
  • Java泛型类型

    当我有一个界面时 public interface Foo
  • 在 Angular 4 中处理来自 Api 的过期令牌

    我需要帮助来处理我的角度应用程序中的过期令牌 我的 api 已过期 但我的问题是当我忘记注销我的角度应用程序时 一段时间后 我仍然可以访问主页但没有数据 我能做点什么吗 有没有可以处理这个问题的库 或者有什么我可以安装的吗 更好 如果我什么
  • 将隐藏(生物识别)数据附加到 pdf 上的数字签名

    我想知道是否可以使用 iText 我用于签名 或 Java 中的其他工具在 pdf 上添加生物识别数据 我会更好地解释一下 在手写板上签名时 我会收集签名信息 例如笔压 签名速度等 我想将这些信息 java中的变量 与pdf上的签名一起存储

随机推荐