• 使用 Java api在MongoDB中获取最后插入的文档ID


    1. 概述

    有时,我们需要刚刚插入 MongoDB 数据库的文档的 ID。 例如,我们可能希望将 ID 作为对调用者的响应发送回去或记录创建的对象以进行调试。

    在本教程中,我们将了解如何在 MongoDB 中实现 ID,以及如何通过 Java 程序检索我们刚刚插入集合中的文档的 ID。

    2. MongoDB文档的ID是什么?

    与在每个数据存储系统中一样,MongoDB 需要为集合中存储的每个文档分配一个唯一标识符。 这个标识符相当于关系数据库中的主键。

    在 MongoDB 中,这个 ID 由 12 个字节组成:

    • 一个 4 字节的时间戳值表示自 Unix 纪元以来的秒数
    • 每个进程生成一次的 5 字节随机值。 这个随机值对于机器和程序是唯一的。
    • 一个 3 字节的递增计数器

    ID 存储在名为 _id 的字段中,由客户端生成。 这意味着必须在将文档发送到数据库之前生成 ID。 在客户端,我们可以使用驱动程序生成的 ID 或生成自定义 ID。

    我们可以看到,同一个客户端在同一秒内创建的文档的前 9 个字节是相同的。 因此,在这种情况下,ID 的唯一性依赖于计数器。 该计数器可让客户在同一秒内创建超过 1600 万份文档。

    虽然它以时间戳开头,但我们应该注意不要将标识符用作排序标准。 这是因为不能保证在同一秒内创建的文档按创建日期排序,因为计数器不能保证是单调的。 此外,不同的客户端可能有不同的系统时钟。

    Java驱动程序为计数器使用随机数生成器,它不是单调的。这就是为什么我们不应该使用驱动程序生成的ID来按创建日期排序。

    3. ObjectId 类

    唯一标识符存储在 ObjectId 类中,该类提供了方便的方法来获取存储在 ID 中的数据,而无需手动解析。

    例如,我们可以通过以下方式获取 ID 的创建日期:

    Date creationDate = objectId.getDate();
    
    • 1

    同样,我们可以以秒为单位检索 ID 的时间戳:

    int timestamp = objectId.getTimestamp();
    
    • 1

    ObjectId 类还提供了获取计数器、机器标识符或进程标识符的方法,但它们都已弃用。

    4. 获取 ID

    要记住的主要事情是,在 MongoDB 中,客户端在将 Document 发送到集群之前生成唯一标识符。 这与关系数据库中的序列相反。 这使得检索此 ID 变得非常容易。

    4.1. 驱动程序生成的 ID

    生成Document 的唯一 ID 的标准且简单的方法是让驱动程序完成这项工作。 当我们向 Collection 中插入一个新的 Document 时,如果 Document 中不存在 _id 字段,则驱动程序会在向集群发送插入命令之前生成一个新的 ObjectId

    我们将新的 Document 插入您的 Collection 的代码可能如下所示:

    Document document = new Document();
    document.put("name", "Shubham");
    document.put("company", "Baeldung");
    collection.insertOne(document);
    
    • 1
    • 2
    • 3
    • 4

    我们可以看到,我们从未指明 ID 必须如何生成。

    insertOne() 方法返回时,我们可以从 Document 中获取生成的 ObjectId

    ObjectId objectId = document.getObjectId("_id");
    
    • 1

    我们还可以像 Document 的标准字段一样检索 ObjectId,然后将其转换为 ObjectId

    ObjectId oId = (ObjectId) document.get("_id");
    
    • 1

    4.2. 定制 ID

    另一种检索 ID 的方法是在我们的代码中生成它并像任何其他字段一样将其放入 Document 中。 如果我们将带有 _id 字段的 Document 发送给驱动程序,它不会生成新的。

    在某些情况下,我们可能需要在将 Document 插入 Collection 之前需要 MongoDB Document 的 ID。

    我们可以通过创建类的新实例来生成一个新的 ObjectId

    ObjectId generatedId = new ObjectId();
    
    • 1

    Or, we can also invoke the static get() method of the ObjectId class:

    ObjectId generatedId = ObjectId.get();
    
    • 1

    然后,我们只需要创建我们的 Document 并使用生成的 ID。 为此,我们可以在 Document 构造函数中提供它:

    Document document = new Document("_id", generatedId);
    
    • 1

    或者,我们可以使用 put() 方法:

    document.put("_id", generatedId);
    
    • 1

    当使用用户生成的 ID 时,我们必须谨慎地在每次插入之前生成一个新的 ObjectId,因为重复的 ID 是被禁止的。 重复的 ID 将导致带有重复键消息的 MongoWriteException异常。

    ObjectId 类提供了几个其他构造函数,允许我们设置标识符的某些部分:

    public ObjectId(final Date date)
    public ObjectId(final Date date, final int counter)
    public ObjectId(final int timestamp, final int counter)
    public ObjectId(final String hexString)
    public ObjectId(final byte[] bytes)
    public ObjectId(final ByteBuffer buffer)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    但是,当我们使用这些构造函数时应该非常小心,因为提供给驱动程序的 ID 的唯一性完全依赖于我们的代码。 在这些特殊情况下,我们可能会遇到重复键错误:

    • 如果我们多次使用相同的日期(或时间戳)和计数器组合
    • 如果我们多次使用相同的十六进制 Stringbyte 数组或 ByteBuffer

    5. 结尾

    在本文中,我们了解了文档的 MongoDB 唯一标识符是什么以及它是如何工作的。 然后,我们看到了如何在将 Document 插入 Collection 之后甚至在插入它之前检索它。


    <<<<<<<<<<<< [完] >>>>>>>>>>>>

  • 相关阅读:
    gland 管理 go 依赖包
    机器学习——推荐算法
    我原本写了一个网页并且上线了,后面把内容全部改过,为什么打开网页还是显示旧的内容。(浏览器缓存已清理)
    vue-cli版本号始终是2.9.6,且无法删除,安装更新无效的问题。
    2022年中南大学夏令营面试经验
    力扣(LeetCode)130. 被围绕的区域(C++)
    ChatGPT在测试计划中的应用策略
    Java8中的日期时间API
    【Linux】Shell脚本(文件操作)
    ruoyi-cloud-plus添加一个不要认证的公开新页面
  • 原文地址:https://blog.csdn.net/wjw465150/article/details/127915661