创建并添加到 collection 如果不存在 sails.js

Create and Add to collection if not exists sails.js

我对 sails.js 和 node.js 都很陌生,所以这可能不是 Sails 特定的问题,但我创建了一个用户和标签模型,这样一个用户有很多标签,反之亦然。用户模型的相关属性为:

# models/User.js
tags      : { collection: 'Tag', via: 'users' },
add_tag: function( name ) {
  var self = this;
  Tag.findOne({ name: name })
  .then( function( found ){
    if( found ) {
      sails.log.info('found tag ' + found)
      found.users.add( self.id );
      self.save( sails.log.info );
    } else {
      sails.log.info('didnt find tag, creating with ' + self.id + ' and ' + name);
      Tag.create({ name: name, users: [ self.id ] }).exec( console.log );
    }
  });
},

以及标签模型的:

name     : { type: 'string', required: true, index: true },
users    : { collection : 'User', via: 'tags' },

现在当我 运行 sails console 我使用以下测试:

sails> var user = null; User.find().exec( function( err, u ) { user= u[0]; });
undefined
sails> user.add_tag('cataclysmic');
undefined
sails> info: didnt find tag, creating with 2 and cataclysmic

它一直挂在那里,直到我按 Enter 或 Ctrl+C 并且没有创建标签。

同样,我对 Node 和 Sails 非常陌生,来自 Rails 背景,所以它可能是非常愚蠢的东西。另外,如果我没有正确使用承诺,请告诉我,因为我对这些也很陌生。

更新

根据 Travis Webb 的建议,我尝试转换为 findOrCreate 但遗憾的是它仍然无法正常工作:

add_tag: function( name ) {
  var self = this;
  Tag.findOrCreate({ name: name })
  .then( function( tags ){
    sails.log.info( JSON.stringify(tags) );
    return tags;
  }).spread( function( tag ){ // should get the first matching tag
    sails.log.info( JSON.stringify(tag) );
    Tag.update( { name: tag }, { user: self.id } )
    .exec( sails.log.info );
  }).catch( sails.log.error ); //no errors are logged either
},

使用与上面相同的 sails console 命令调用 add_tag() 我只得到 undefined 和 none 的日志语句被执行。特拉维斯,我在这个实现中做错了什么吗?

最终更新

我使用下面 Jason 的回答来创建我的最终答案:

add_tag: function( name ) {
  var self = this;
  Tag.findOrCreate({ name: name }, { name: name })
  .then( function( tag ){
    tag.users.add( self.id );
    tag.save( sails.log.info );
  }).catch( sails.log.error );
},

我的代码没有显示任何错误的原因是我在 Tag.js 中使用生命周期回调在每次更新时递增优先级计数器,如下所示:

afterValidate: function() {
 this.priority++;
}

当我应该像这样调用链中的下一个回调时:

afterValidate: function( values, cb ) {
  values.priority++;
  cb();
}

你想不到的事情之一来自 Rails 背景 :P

您使用 findOrCreate 不正确。

函数定义为.findOrCreate( search criteria, [values, callback] )

您可能需要将函数修改为:

add_tag: function( name ) {
  var self = this;

  //for clarity we won't set the user when creating tags, 
  //instead we'll do it in the callback, so its the same for existing and new tags.
  Tag.findOrCreate({ name: name }, { name: name })
  .then( function( tag ){
    tag.users.add( self.id );
    tag.save( sails.log.info );

  });
},