我之前使用了一个快捷方式,通过连接各个字段来创建“唯一ID”,从而制作了Mongo数据库的主键
我现在想将其更改为实际使用ObjectId。这样做的最佳方法是什么?我有一些3M文件,并希望尽可能减少破坏性。
一个简单的方法是将网站关闭一段时间,然后将每个文档从一个文件复制到另一个使用ObjectIds的文档,但是如果可以的话我想保持应用程序运行。我想有一种方法是在迁移发生时写入两段时间,但这需要我有两个相似的代码库,所以我想知道是否有办法避免这一切。
提供一些额外信息: 它只是一个没有被其他人引用的集合。我有另一个MySQL数据库,其中包含一些用于创建从MongoDB集合中读取的查询的值。
我正在使用PyMongo / Mongoengine库与Python中的MongoDB交互,我不知道是否可以只更改集合的主键。
答案 0 :(得分:3)
如果网站没有自行关闭,您不应该因为任何原因而关闭网站。 :)
无论您拥有多少百万条记录,问题的解决方案都取决于您如何使用ID。
如果使用这些ID交叉引用不同集合中的文档,则对于每个更新的对象,您将更新引用此对象的所有其他对象。
首先,应更新系统以停止以旧方式创建新对象。如果您的系统可以轻松地执行此操作,那么您可以非常轻松地更新数据库。如果这个改变不容易,那么你的系统有一些架构问题,你应该先改变它。如果是这种情况,请更新您的问题,以便我可以更新我的答案。
由于我对您的应用程序和数据一无所知,我所说的内容过于笼统。让我们调用你想要更新coll_bad_id的集合。此集合中的每个项目都在其他集合中引用,如coll_poor_guy和coll_wisdom_searcher。我如何做到这一点是一次在coll_bad_id上运行一个项目,如下所示:
1. read one item
2. update _id with new style of _id
3. insert item back to collection
-- now we have two copies of the same item one with old-style id, one with new
4. update each item referencing this to use new style id
5. remove the duplicate item with old-style id from collection
有一件事你应该记住,bson ObjectId保留日期/时间数据非常有用。由于您在一天内重建所有这些对象,因此您的ObjectId将不会反映这些项目的正确创建时间。对于新添加的项目,他们会。您可以将第一个新添加的项目记录为具有正确创建时间的ID的项目的里程碑。
UPDATE:在Mongo shell上运行的代码示例。 这不是最有效的方法;但是运行是安全的,因为我们在用新的_id添加它们之前不删除任何东西。通过向find()调用添加查询,可以更好地做到这一点。
var cursor = db.testcoll.find()
cursor.forEach(function(item) {
var oldid= item._id; // we save old _id to use for removal below.
delete item._id; // When we add an item without _id, Mongo creates a unique _id.
db.testcoll.insert(item); // We add item without _id.
db.testcoll.remove(oldid); // We delete the item with bad _id.
});