Sails.js模型 - 插入或更新记录

Cri*_*ash 9 javascript sails.js

一直在尝试Sails.js,我正在编写一个从第三方API导入数据并保存到MySQL表中的应用程序.基本上我正在尝试将数据同步到我的应用程序以进行进一步分析,更新我的记录或根据需要创建新记录.

我查看了Sails的API,我看到了查找,创建和更新记录的方法,但没有根据情况插入/更新记录的内置方法.我是否忽视了某些事情,或者我是否需要自己实施?

如果我必须自己实现,有没有人知道插入/更新的良好设计模式?

这就是我认为它可能看起来像......

_.each(importedRecords, function(record){
  MyModel.find({id: record.id}).exec(function findCB(err, found){
    if(found.length){
      MyModel.update(record.id, task).exec(function(err, updated){
        if(err) { //returns if an error has occured, ie id doesn't exist.
          console.log(err);
        } else {
          console.log('Updated MyModel record '+updated[0].name);
        }
      });
    }else{
       MyModel.create(record).exec(function(err, created){
         if(err) { //returns if an error has occured, ie invoice_id doesn't exist.
           console.log(err);
         } else {
           console.log('Created client record '+created.name);
         }
       });
     }
   });
 });
Run Code Online (Sandbox Code Playgroud)

我是朝着正确的方向前进,还是有更优雅的解决方案?

此外,我在这个应用程序中处理了很多不同的模型,这意味着在我的每个模型中重新创建这个代码块.有没有办法可以扩展基础Model对象,为所有模型添加此功能.

谢谢,约翰

Sta*_*ski 21

我已经重写了Critical Mash代码,因此代码更少,更通用.现在,您可以像调用findOrCreate一样调用updateOrCreate.看起来像这样:

module.exports.models = {
    updateOrCreate: function(criteria, values){
        var self = this; // reference for use by callbacks
        // If no values were specified, use criteria
        if (!values) values = criteria.where ? criteria.where : criteria;

        return this.findOne(criteria).then(function (result){
          if(result){
            return self.update(criteria, values);
          }else{
            return self.create(values);
          }
        });
    }
};
Run Code Online (Sandbox Code Playgroud)

这样你就可以用同样的方式编写标准.无需处理密钥,代码更简单.

  • 美丽的答案.有了你的许可(和信用),我想基于此创建一个对Sails的拉取请求. (3认同)

Ken*_*min 10

Sails 0.10有findOrCreate(criteria, attributes, callback),请参阅Sails Docs.

criteria 是"查找"位的搜索条件(与find()的语法相同).

attributes 是否为"create"位找不到的数据(与create()的语法相同).

这是一个例子:

MyModel.findOrCreate({name:'Walter'},{name:'Jessie'}, function (err, record){ console.log('What\'s cookin\' '+record.name+'?');

另请注意,Waterline存储库中记录了其他复合查询方法(请参阅示例测试)和Waterline文档:

默认情况下,Collection实例上可以使用以下每种基本方法:

  • 找一个
  • 创建
  • 更新
  • 破坏
  • 计数

此外,您还有以下辅助方法:

  • createEach
  • findOrCreateEach *< - 看起来像你需要的(提示使用条件/属性数组)*
  • findOrCreate
  • findOneLike
  • findLike
  • 以..开始
  • 以..结束
  • 包含

根据您的Collection属性,您还可以使用动态查找器.因此,给定name属性,将提供以下查询:

  • findOneByName
  • findOneByNameIn
  • findOneByNameLike
  • findByName
  • findByNameIn
  • findByNameLike
  • countByName
  • countByNameIn
  • countByNameLike
  • nameStartsWith
  • nameEndsWith
  • nameContains

至于忽略某些东西,它就在那里,但它不在主要的Sails文档中,所以答案是肯定的,不是,所以不要流汗:)


mdu*_*sch 4

你的解决方案是正确的。对于 Waterline(sails.js 的 ORM)没有其他方法可以做到这一点。但有几个数据库有针对这种情况的函数:

MySQL

REPLACE INTO table SET id = 42, foo = 'bar'; (使用主键或唯一键。如果使用 auto_increment 就太糟糕了;-)

在 Waterline 中您可以使用模型。query() -执行直接 SQL 的函数(参见:http ://sailsjs.org/#/documentation/reference/waterline/models/query.html )

MongoDB

db.collection.update(
  <query>,
  <update>,
  { upsert: true }
)
Run Code Online (Sandbox Code Playgroud)

upsert 标志的含义是:如果由于在查询中没有找到任何内容而无法更新它,请创建此元素!

在 Waterline 中您可以使用模型。native() -执行直接 mongoDB 命令的函数(参见:http ://sailsjs.org/#/documentation/reference/waterline/models/native.html )

结论

您需要快速执行(当然,如果您有很多请求),我建议使用本机/sql 函数。但总的来说,我真的很喜欢 ORM 系统的灵活性,每次使用特定于数据库的函数时,它都更难处理。