gpt4 book ai didi

mongodb - 如何在 reactivemongo 中插入后获取文档对象 ID?

转载 作者:可可西里 更新时间:2023-11-01 09:12:14 25 4
gpt4 key购买 nike

我看到这个问题似乎很早就有人问过(差不多 3 年前),但从那时起响应式(Reactive) mongo 库可能会有很多变化。

我正在使用 2.4 版本的 play 插件,但是 reactivemongo.api.commands.WriteResult 似乎没有任何 API 来获取文档对象 ID。

现在我可以开始自己设置对象 ID,但我认为这不是一个令人信服和正确的想法,因为我创建 ID 的机器上的某些唯一值可能与另一台机器不同,并且为了简单起见我想让这个由 mongo db 处理。

是的,如果有某种方法可以让我获得插入文档的 ID,那就太好了,否则我必须回退到自己设置 ID 的方式,这是我试图避免的事情。

最佳答案

至少有两种正确的方法可以解决这个问题。实际上,第二个更像是一个 hack,但它工作正常。我创建了一个 gist with a complete example (tested) .

在客户端生成BSONObjectId

BSONObjectId 有一个名为 generate 的方法,您可以使用它轻松生成唯一 ID。生成的 ID 与 MongoDB 服务器本身生成的 ID 具有相同的结构:

+------------------------+------------------------+------------------------+------------------------+
+ timestamp (in seconds) + machine identifier + thread identifier + increment +
+ (4 bytes) + (3 bytes) + (2 bytes) + (3 bytes) +
+------------------------+------------------------+------------------------+------------------------+

(取自 ReactiveMongo 的 BSONObjectId.generate 的 javadoc)

示例代码:

val id = BSONObjectId.generate()
collection.insert(BSONDocument("_id" -> id, "foo" -> "bar"))

生成的 ID 不会与服务器生成的完全相同。具体来说,machine identifierthread identifier 很可能完全不同。然而,在大多数(所有?)情况下,这无关紧要,因为碰撞的风险可以忽略不计,所以我认为这是最好的方法。

您还应该检查 insert 返回的值。如果失败,您可以生成一个新 ID 并再次尝试插入。这样你的代码应该是防弹的。请记住限制重试次数,并可能在每次尝试之间添加一些随机延迟。

使用BSONCollection.findAndUpdate

如果出于某些不明确的原因,您确实需要在服务器端生成 ID,那么此解决方案应该可以做到这一点,从而避免竞争条件或任何其他查询,因此它是最佳选择,尽管有些 hacky。诀窍是使用 MongoDB 的 findAndModify。这样,您将获得 FindAndModifyResult 而不是 WriteResult,这使您可以访问插入的文档。示例:

val resultFuture = collection.findAndUpdate(
selector = BSONDocument("foo" -> -1), // Assuming that there's no document with "foo" equal to -1, otherwise THIS CODE MAY EXPLODE
update = BSONDocument("foo" -> "bar"),
fetchNewObject = true,
upsert = true)
val idFuture: Future[BSONObjectId] = resultFuture.map { result =>
val doc = result.value.get // WARNING: I'm using get for simplicity, but you shouldn't: it may throw an exception
doc.getAs[BSONObjectId]("_id"))
}

请注意,您必须提供一个从不选择文档的选择器,否则这将更新现有文档而不是插入新文档。此外,您需要在 update 中覆盖这些字段,否则它将使用 selector 中的值。

奖励:为增量 ID 使用单独的集合

您还可以创建一个额外的集合来保留最新的 ID,如 MongoDB's documentation 中所述。 .只要您使用 findAndModify 同时获取新 ID 并增加值,这应该是安全的。缺点?一个额外的集合和一个额外的查询,但在某些情况下您仍然需要自动递增的唯一 ID,因此可能值得考虑。

关于mongodb - 如何在 reactivemongo 中插入后获取文档对象 ID?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36179578/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com