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

时间:2014-11-20 03:08:07

标签: javascript mongodb meteor

假设您正在创建一个聊天室应用程序,用户可以在其中设置昵称,但昵称必须是聊天室唯一的。我用这样的方法实现了这个:

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很新,所以我不确定哪种方法更好。两种方式看起来都是一样的,但我觉得如果两个用户试图同时设置相同的昵称,第一种方式可以允许相同的昵称。

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

1 个答案:

答案 0 :(得分:1)

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

http://docs.mongodb.org/manual/tutorial/create-a-unique-index/