我有一个主寄存器和x个子寄存器,它们将数据流传输到主寄存器。我在夜间使用主寄存器同步这些寄存器。因此,白天将在x1,x2,...xn
中创建数据,并在晚上将所有数据发送到主寄存器。
这不是很可能,但可能是例如x1
和x2
生成相同的_id
。现在,如果我同步它们,第一个寄存器将创建文档,第二个寄存器将插入(并因此覆盖)我的文档。
为了防止我当前将原始_id
保存在字段refId
下,这非常糟糕,因为我无法使用主寄存器上的所有引用和大多数函数。
我计划切换到自动增量_ids
,但我读到如果您计划扩展,这是您不应该做的事情:
https://blog.serverdensity.com/switching-to-mongodb-and-auto-increment/ https://docs.mongodb.org/manual/tutorial/create-an-auto-incrementing-field/
我已经保存了我的文档来自哪个子寄存器。因此,我可以检查_id
是否存在,但是有另一个子寄存器。如果是这样,我可以为新文档生成新的_id
,并将新的_id
返回到我的子寄存器。这听起来很容易乍一看,但我的文档中有很多引用。
使用可能的重复ID处理此问题的好方法是什么?是否有一种更简单但有效的方法来解决这个问题?例如。自动为24位数字ObjectId添加前缀。
答案 0 :(得分:1)
As it is unlikely(虽然并非不可能)在不同的子寄存器中生成两个相同的ObjectId,您可以在错误处理程序中处理重复的ObjectIds。如果存在唯一的密钥冲突并且源寄存器中存在差异,则可以生成新的ObjectId。由于不会频繁调用错误处理程序,因此可以添加更复杂的逻辑而不会影响整体性能。
例如,您可以通过克隆源记录并删除原始文件来生成新的ObjectId,或者,您也可以创建自己的ObjectId并将machineId替换为registerId。
答案 1 :(得分:0)
最终的解决方案是创建一个自定义的猫鼬ObjectId。正如本文https://docs.mongodb.org/manual/reference/object-id/#ObjectIDs-BSONObjectIDSpecification中所提到的,猫鼬_id
由几个部分组成,即使它们在不同的机器上生成,也不太可能发生两个_id
碰撞。为了更好地控制此过程,我可以控制_id
中的processId部分。每个子寄存器都有自己的processID。
为了达到这个目的,我生成了两个函数:
1)检查_id
的覆盖值是否可用,有效以及寄存器是否为本地寄存器(主寄存器不需要修改)。条目仅在我的本地注册中生成。
2)修改_id
mongoose = require('mongoose')
ObjectId = mongoose.Types.ObjectId
registerType = require('./register-config.js').getType()#function gives back local/national
exports.useProcessId = ()->
return process.env.REGISTER_PROCESS_ID? && process.env.REGISTER_PROCESS_ID.length == 4 && registerType == 'local'
exports.changeMongooseId = (data, next) ->
id = data._id.toString()
data._id = new ObjectId(id.slice(0,6) + process.env.REGISTER_PROCESS_ID + id.slice(10,24))
return next()
在将新文档保存到集合之前调用此函数:
instituteSchema.pre('save', (next) ->
data = @
async.parallel
eprd: (next)->
validateEPRD(data, next)
changeMongooseId: (next)->
if useProcessId then processIdConfig.changeMongooseId(data, next) else return next()
(err)->
return next new Error(err) if err?
return next()
)
我不需要在更新等方面调用该函数,因为此时它已经具有唯一的_id
。