使用 Java api在MongoDB中获取最后插入的文档ID
创始人
2024-01-29 17:44:06

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();

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

int timestamp = objectId.getTimestamp();

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

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

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

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

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

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

4.2. 定制 ID

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

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

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

ObjectId generatedId = new ObjectId();

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

ObjectId generatedId = ObjectId.get();

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

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

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

document.put("_id", generatedId);

当使用用户生成的 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)

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

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

5. 结尾

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


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

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
函授本科是什么 自考本科还是函... 很多小伙伴在选择学历提升方式的时候,可能会感到很迷茫,不知道报考自考本科还是函授本科,两者有什么区别...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
安徒生童话有哪些 安徒生童话的... 从德国汉堡港乘轮船渡波罗的海抵丹麦王国,就到了安徒生的祖邦。安徒生(1805-1875)以童话作品闻...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...