Javascript 在Meteor中使用复杂的更新选择器进行原子操作

Javascript 在Meteor中使用复杂的更新选择器进行原子操作,javascript,mongodb,meteor,Javascript,Mongodb,Meteor,假设您正在制作聊天室应用程序,用户可以在其中设置昵称,但昵称必须是聊天室独有的。我已经用这样的方法实现了这一点: Meteor.methods({ setNickname: function( nickname ) { check( nickname, String ); if ( ! this.userId ) { /* throw error */ } var chatroom = Chatroom.collection.findOne({ 'us

假设您正在制作聊天室应用程序,用户可以在其中设置昵称,但昵称必须是聊天室独有的。我已经用这样的方法实现了这一点:

Meteor.methods({
  setNickname: function( nickname ) {
    check( nickname, String );

    if ( ! this.userId ) { /* throw error */ }

    var chatroom = Chatroom.collection.findOne({
      'users._id': this.userId
    });

    if ( _.findWhere( chatroom.users, { nickname: nickname } ) ) { /* throw error */ }

    Chatroom.collection.update({
      'users._id': this.userId,
    }, {
      $set: {
        'users.$.nickname': nickname
      }
    });
  }
});
这感觉很笨拙,我想知道验证逻辑与查询分离时是否会出现并发性问题。我在想,我可以用如下方式将此逻辑转移到查询本身中:

Meteor.methods({
  setNickname: function( nickname ) {
    check( nickname, String );

    if ( ! this.userId ) { /* throw error */ }

    Chatroom.collection.update({
      'users._id': this.userId,
      'users.nickname': {
        $ne: nickname
      }
    }, {
      $set: {
        'users.$.nickname': nickname
      }
    });
  }
});
我对MongoDB相当陌生,所以我不确定哪种方法更好。这两种方法似乎都是一样的,但我觉得如果两个用户试图同时设置相同的昵称,第一种方法可以允许使用相同的昵称


因此,基本上,我应该使用复杂的更新选择器来确保这样的操作是原子的吗?

一种方法是在mongodb中对昵称和聊天室id设置一个唯一的索引。这将防止插入或更新违反该索引。如果试图插入当前存在的昵称,则必须捕获回调中的错误


以下是MongoDB文档另一页的引用:“唯一约束适用于集合中的单独文档。也就是说,唯一索引防止单独的文档对索引键具有相同的值,但索引不阻止文档具有多个元素或索引数组中嵌入的文档具有相同的值。“因此,既然我将用户成员身份作为聊天室文档中的嵌入数组元素进行非规范化,这难道不意味着唯一索引将不起作用吗?你是说每个聊天室将有一个文档吗?”?您能用一个模式示例更新您的问题吗?