【问题标题】:How do I generate a unique id using Lucene?如何使用 Lucene 生成唯一 ID?
【发布时间】:2011-02-20 18:28:52
【问题描述】:

我正在使用 Lucene 来存储(以及索引)各种文档。

每个文档都需要一个持久的唯一标识符(用作 URL 的一部分)。

如果我使用的是 SQL 数据库,我可以使用 integer primary key auto_increment(或类似的)字段为添加的每条记录自动生成唯一 ID。

有没有办法用 Lucene 做到这一点?

我知道 Lucene 中的文档有编号,但注意到这些编号会随着时间的推移重新分配。

(我使用的是 Java 版本的 Lucene 3.0.3。)

【问题讨论】:

  • 你不能只索引一个 UUID.randomUUID() 并将其用作永久密钥吗?
  • 理想情况下,我希望我的 ID 更短。

标签: java lucene


【解决方案1】:

正如 larsmans 所说,您需要将其存储在单独的字段中。我建议您将字段编入索引并进行存储,并使用 KeywordAnalyzer 对其进行索引。 您可以在内存中保留一个计数器并为每个新文档更新它。

剩下的就是持久化问题——Lucene进程停止时如何存储最大id。一种可能性是使用保存最大 id 的文本文件。

我相信Flexible Indexing 将允许您将最大 id 作为“全局”字段添加到索引中。如果你愿意使用 Lucene 的主干,你可以尝试灵活的索引,看看它是否符合要求。

【讨论】:

    【解决方案2】:

    对于类似的情况,我使用以下算法(与Lucene无关,但你可以使用它)。

    • 创建新的AtomicLong。从System.currentTimeMillis()System.nanoTime() 获得的初始值开始
    • 每个下一个 ID 都是通过在该 AtomicLong 上调用 .incrementAndGet.getAndIncrement 生成的。
    • 如果系统重新启动,AtomicLong 在启动期间再次初始化为当前时间戳。

    优点:简单、有效、线程安全、非阻塞。如果您需要集群 id 支持,只需在现有 long 之上为 hi/lo algorithm 添加空间或牺牲一些高字节。

    缺点: 如果添加新实体的频率超过 1/ms(对于 System.currentTimeMillis())或 1/ns(对于 System.nanoTime()),则不起作用。不能容忍时钟异常。

    可以考虑使用UUID 作为另一种选择。 UUID 中重复的概率为virtually non-existant

    【讨论】:

      【解决方案3】:

      编辑:一些评论者提出了这种方法可能存在的问题,我没有时间彻底测试它。我把它留在这里是因为 Yuval F. 提到了它。请不要不必要地投反对票。

      给定一个IndexWriter w,您可以使用w.maxDoc() + 1 作为一个ID,并将它(作为一个字符串)存储在一个单独的Field 中。确保Fieldstored

      【讨论】:

      • 为什么要存储 id 字段而不对其进行索引?这不是说我不能按 id 搜索吗?
      • 另外,这会不会受到合并的影响,并在删除的文档被修剪时重用 id?
      • 对不起@Dave,误读了你的问题。当然,您可以根据需要对其进行索引。 @Simon Svensson:API 文档状态“返回此索引中的文档总数 (...) 不计算删除”。
      • 我认为这行不通。假设有 n 个文档。添加n+1。删除一个。加上另一个。现在您有两个 ID 为 n+1 的文档。 (如果你合并索引等,你也会变得很糟糕。)
      • @Xodarap:如果我正确阅读了 API 文档(“不计算删除”),那么这种方法确实可以防止这种情况。事实上,这似乎就是为什么IndexWriter 同时拥有maxDocnumDocs 方法。
      【解决方案4】:

      尝试在您正在索引的数据源中找到一个唯一值,并将其存储在 lucene 文档中。数据源可以是 mysql 数据库、文件系统中的文件等。

      例如,如果您正在索引 mysql 数据库中的内容,则可以使用表名和主键 ID“tablename_rowID”组合一个唯一 ID。

      假设您从两个表“pages”和“cmets”表中建立索引;对于 pages 表中的每一行,您可以使用“page_28”为 pages 表中 id 为 28 的行生成一个唯一 id。同样,假设您索引 cmets 表中的第 36 行,您的唯一 ID 将是“comment_36”。

      如果所有选项都失败,那么我会坚持使用 UUID。加上一些额外的偏执,这可能是一个附加到 now() 时间戳的 UUID。

      【讨论】:

        猜你喜欢
        • 2014-06-13
        • 2018-05-04
        • 1970-01-01
        • 2013-04-19
        • 2012-02-22
        • 1970-01-01
        • 1970-01-01
        • 2015-09-25
        相关资源
        最近更新 更多