【问题标题】:Using "unique" with Nested Objects in Mongoose在 Mongoose 中对嵌套对象使用“唯一”
【发布时间】:2013-03-24 08:23:29
【问题描述】:

所以我有一个带有嵌套 profile 属性的用户架构,并且我想确保当 profile 属性存在时所有配置文件 ID 都是唯一的:

UserSchema = new Schema {
    ...
    ...
    profile : {
        id : {
           type : String
           unique : true
           sparse : true
        }
        ...
        ...
    }
}

但是,在运行测试时,我可以使用相同的 profile.id 值保存两个不同的用户。嵌套文档是否没有强制执行唯一属性?我错过了什么吗?

打开日志后,我可以看到这样的输出(我已经删除了大部分字段):

Mongoose: users.ensureIndex({ email: 1 }) { safe: undefined, background: true, unique: true }  
Mongoose: users.insert({ profile: { id: '31056' }) {}  
Mongoose: users.ensureIndex({ 'profile.id': 1 }) { safe: undefined, background: true, sparse: true, unique: true }  
Mongoose: users.insert({ profile: { id: '31056' }) {}

仍在插入重复值。

【问题讨论】:

  • 是的,对嵌套文档强制执行唯一索引。可能发生的情况是它无法创建索引,因为您已经有了重复项。请参阅this answer 了解有关调试此问题的一些技巧。
  • 感谢 Johnny 的建议,但我一直在测试之间删除数据库,所以我认为情况并非如此。我将使用您提供的链接中的步骤进行一些调试。
  • 索引创建也是异步的。这可能是一种竞争条件。尝试在插入之前等待索引事件。
  • User.on('index', function (err) { ... })
  • 感谢 Aaron,解决了这个问题。日志似乎表明索引创建延迟,这表明您建议的竞争条件。很棒的工具,再次感谢您的帮助!

标签: node.js mongodb mongoose


【解决方案1】:

也许它仅在嵌套属性内验证为唯一。我自己从不信任unique,总是去手动验证,这样我可以有更多的控制权:

我自己从未在 Mongoose 中处理过嵌套文档,也不太确定它是否会起作用,但至少让您有一个想法:

User.schema.path('profile.id').validate(function(value, respond) {  
  mongoose.models["User"].findOne({ profile.id: value }, function(err, exists) {
    respond(!!exists);
  });
}, 'Profile ID already exists');

【讨论】:

  • 感谢您的解决方案,如果嵌套文档上的唯一性不符合我的预期,我将使用它。
【解决方案2】:

Aaron 的建议修复了由异步创建的索引引起的竞态条件。我等待执行我的用户模式的单元测试,直到发出索引事件:

User.on('index', function (err) { ... })

【讨论】:

    猜你喜欢
    • 2013-04-02
    • 2017-10-03
    • 2017-06-26
    • 1970-01-01
    • 2014-04-03
    • 2014-08-15
    • 2013-06-03
    相关资源
    最近更新 更多