文档索引

本文档描述了如何将文档添加到索引中。

组件

  • Document - 包含实际文档及其字段。
  • RSAddDocumentCtx - 在索引过程中使用的每个文档的状态。索引完成后将丢弃该状态。
  • ForwardIndex - 包含文档中找到的术语。正向索引用于编写InvertedIndex
  • InvertedIndex - 将术语映射到适用文档中出现的索引。

架构

索引过程从创建新的RSAddDocumentCtx并向其中添加文档开始。在内部,这分为几个步骤。

  1. 提交

    创建一个DocumentContext,并将其与从输入接收的文档相关联。提交过程还将执行一些初步缓存。

  2. 预处理

    提交文档后,对它进行预处理。预处理对所有文档输入字段执行无状态处理。对于文本字段,这意味着对文档进行标记化并创建正向索引。预处理器将把此信息存储在AddDocumentCtx中的每个字段变量中。此计算结果随后在索引阶段写入持久索引。

    如果文档足够大,则预处理将在单独的线程中完成,这允许并发预处理,还可以避免阻塞其他线程。如果文档较小,则预处理将在主线程中完成,从而避免了附加上下文切换的开销。SELF_EXC_THRESHOLD宏包含“足够大”的阈值。

    预处理文档后,提交它以进行索引。

  3. 索引

    正确的索引包括提交预处理阶段的预计算结果。它在一个线程中完成,并且采用队列的形式。

    因为文档必须按其文档 ID 分配的顺序准确地写入索引,并且因为索引过程还必须让位于其他潜在的索引过程,所以你最终可能会遇到文档 ID 以无序方式写入索引的情况。为了解决这个问题,必须明确定义实际写入文档的顺序。如果只有一个线程写入文档,那么此线程在写入时不必担心无序 ID。

    拥有单个后台线程也有助于在多个领域进行优化,正如稍后所见。基本思想是,当有大量文档排队等待索引线程时,索引线程可以将它们视为批处理命令,从而大大减少 GIL 的锁定/解锁次数以及术语密钥需要打开和关闭的次数。

  4. 跳过已编入索引的文档

    以下阶段可以一次对多个文档进行操作。当一个文档完全编入索引后,它将被标记为已完成。当线程遍历队列时,它将只对尚未标记为已完成的项目执行处理/编制索引。

  5. 术语合并

    当队列中有多个文档时,将执行术语合并或前向索引合并。扫描队列中每个文档的前向索引,并在此基础上构建一个更大的主前向索引。前向索引中的每个条目都包含对原始文档的引用以及正常的偏移量/分数/频率信息。

    创建主前向索引可避免为每个文档多次打开通用术语键。

    如果队列中只有一个文档,则不会创建主前向索引。

    请注意,主前向索引的内部类型实际上不是ForwardIndex

  6. 文档 ID 分配

    此时,GIL 被锁定,并且队列中的每个文档都被分配一个文档 ID。分配在写入索引之前立即完成,以减少锁定 GIL 的次数;因此,GIL 只被锁定一次,即在写入索引之前。

  7. 写入索引

    在锁定 GIL 的情况下,任何待处理的索引数据都将被写入索引。这通常涉及打开一个或多个 Redis 键,并将计算出的数据写入/复制到这些键中。

    完成后,将发送给定文档的回复,并释放AddDocumentCtx

对本页面进行评分