【发布时间】:2013-09-11 16:34:03
【问题描述】:
我有多个发布/订阅服务器尝试在事件发生时更新 MongoDB 数据库。目前,我遇到了一个问题,我需要将条目自动添加到给定的 MongoDB 文档数组中,但是当涉及到谁将条目添加到文档中时,我遇到了竞争条件。我试图使用$addToSet 来完成添加。但是,由于一旦条目在数组内,数组条目就可以更新,因此 addToSet 很难正常工作,因为它会直接比较条目是否在数组内。如下所示的最终结果是我让多个服务器向数组中添加了一个新条目。
以下是我想要的已完成文档的示例:
{
"_id" : ObjectId("522f99a622927d6d65b81dbd"),
"array" : [
{
"type" : "out",
"uuid" : "4f501517-1d10-48c2-91b7-0ca1bda80bd5",
"member_id" : "3847",
"join" : ISODate("2013-09-10T17:13:58.881Z")
}
],
"created" : ISODate("2013-09-10T17:13:58.437Z"),
"name" : "entry"
}
以下是由于竞态条件而发生的情况的示例:
{
"_id" : ObjectId("522f99a622927d6d65b81dbd"),
"array" : [
{
"type" : "out",
"uuid" : "4f501517-1d10-48c2-91b7-0ca1bda80bd5",
"member_id" : "3847",
"join" : ISODate("2013-09-10T17:13:58.881Z")
},
{
"type" : "out",
"uuid" : "4f501517-1d10-48c2-91b7-0ca1bda80bd5",
"member_id" : "3847",
"join" : ISODate("2013-09-10T17:13:58.881Z")
}
],
"created" : ISODate("2013-09-10T17:13:58.437Z"),
"name" : "entry"
}
是否有人成功地在文档中自动添加/修改数组条目,而无需将数组数据完全移出集合?我知道通过将其移出集合,它允许我针对条目建立一个独特的约束,但我宁愿不必这样做。
【问题讨论】:
-
mongodb 中的操作在文档级别始终是原子的。您是否验证了您的应用程序代码是否存在任何可能的错误?对于要在文档中添加两次的数组元素,您必须调用它两次。
-
请记住,这里有多个服务器在运行,这导致了这种情况。尽管由于 MongoDB 的性质,文档是原子的,但使用 $addToSet 不足以确保只有在条目不存在时才会进入。主要是因为数组对象发生了变化,而 $addToSet 在进行直接比较时并没有真正考虑到这一点。也许我错过了什么?
-
我明白你想要表达的观点,但我想提醒你,mongodb 确实获得了lock while performing writes。此外,writes at document level 始终是原子的。因此,虽然您关于 $addToSet 的观点可能是有效的,但这并不意味着 mongoDb 将执行 $addToSet 两次。并且要获得您显示的数据,它需要调用 $addToSet 两次。如果您的应用程序代码没有任何问题(我建议您应该重新验证以确保),这是 mongoDB 的错误!
-
感谢您的宝贵反馈!然而,由于 pub/sub 事件,我们有多个服务器试图几乎同时运行 $addToSet,它不允许 MongoDB 在将条目添加到数组之前进行适当的检查。同样,很可能是由于条目的键/值在最初放入数组后得到更新。
-
我发现以下帖子对我很有帮助。而不是使用 $addToSet 我可以使用 $push 与适当的标准。 stackoverflow.com/questions/4774827/…