使用 Sequelize 在项目数组上创建/更新
Posted
技术标签:
【中文标题】使用 Sequelize 在项目数组上创建/更新【英文标题】:Create/update with Sequelize on an array of items 【发布时间】:2014-12-28 06:09:08 【问题描述】:我创建了一个函数来:
获取一个“标签”数组并查看它们是否已经在数据库中有记录 创建那些不存在的, 并更新那些确实存在的内容 返回一个 json 数组报告每个项目,无论它们是更新/创建的,还是导致错误我设法让它工作了,但我觉得我只是做了一些丑狗的晚餐!
var models = require("../models");
var Promise = models.Sequelize.Promise;
module.exports =
addBeans: function (req, callback)
Promise.map(req.body.beansArr, function (bean)
return models.Portfolio.findOrCreate(where: label: bean, label: bean);
).then(function (results) // Array of 'instance' and 'created' for each bean "findOrCreate(where, [defaults], [options]) -> Promise<Instance>"
var promisesArr = [];
results.forEach(function (result)
if (result[1]) // result[1] = wasCreated
promisesArr.push(Promise.resolve([result[0].dataValues.label, "created"]));
else
promisesArr.push(
models.Portfolio.update(label: result[0].dataValues.label,
where: label: result[0].dataValues.label).then(function ()
return Promise.resolve([result[0].dataValues.label, "updated"])
)
);
);
return promisesArr;
// When it's all done create a JSON response
).then(function (results)
var resultObj = items: []; // JSON to return at the end
Promise.settle(results).then(function (promiseinstances)
for (var i = 0; i < promiseInstances.length; i++)
if (promiseInstances[i].isFulfilled())
resultObj.items.push(
item:
label: promiseInstances[i].value()[0],
result: promiseInstances[i].value()[1],
error: ''
);
else if (promiseInstances[i].isRejected())
resultObj.items.push(
label: promiseInstances[i].value()[0],
result: 'error',
error: promiseInstances[i].reason()
);
// Send the response back to caller
).then(function ()
return callback(null, resultObj);
, function (e)
return callback(e, resultObj);
);
);
;
问题:
是否有更简单或更明显的方法来使用 Sequelize 创建/更新值? 我对@987654322@ 的使用是否适合这种情况?我觉得我把它弄得比它需要的更复杂。我是 Sequelize 和使用 Promises 的新手,如果有人能就此提出建议,我将不胜感激。
【问题讨论】:
【参考方案1】:我觉得这在 CodeReview.SE 上会更好,但我可以看到一些问题。
是否有更简单或更明显的方法来使用 Sequelize 创建/更新值?
好吧,一方面:
.then(function(array)
var newArr = [];
array.forEach(function(elem)
newArr.push(fn(elem);
return newArr;
);
只是
.map(fn)
此外,promise 可以同化,因此您可以从 .then
转换为 return val;
,而不必转换为 return Promise.resolve(val);
。
所以:
).then(function (results) // Array of 'instance' and 'created' for each bean "findOrCreate(where, [defaults], [options]) -> Promise<Instance>"
var promisesArr = [];
results.forEach(function (result)
if (result[1]) // result[1] = wasCreated
promisesArr.push(Promise.resolve([result[0].dataValues.label, "created"]));
else
promisesArr.push(
models.Portfolio.update(label: result[0].dataValues.label,
where: label: result[0].dataValues.label).then(function ()
return Promise.resolve([result[0].dataValues.label, "updated"])
)
);
);
return promisesArr;
)
只是
.map(function(result)
if(result[1]) return [result[0].dataValues.label, "created"];
return models.Portfolio.update(label: result[0].dataValues.label,
where: label: result[0].dataValues.label).
return([result[0].dataValues.label, "updated"]);
);
但是,由于您希望它在解决问题的情况下都能正常工作,因此您必须这样做:
.then(function(results)
return results.map(function(result)
if(result[1]) return [result[0].dataValues.label, "created"];
return models.Portfolio.update(label: result[0].dataValues.label,
where: label: result[0].dataValues.label).
return([result[0].dataValues.label, "updated"]);
);
);
这意味着无论如何它都会解决,然后你会打电话给.settle()
:
.settle().then(function(results)
// your settle logic here
);
注意最后一个:
).then(function ()
return callback(null, resultObj);
, function (e)
return callback(e, resultObj);
);
很简单:
.nodeify(callback);
但是,我建议坚持承诺。
【讨论】:
感谢一百万!一个问题:“承诺同化”是什么意思?我虽然用'return val;'我将 'val' 作为参数传递给使用 'then' 展开的函数(例如:.then(function(val)); ),并使用 'Promise.resolve(val)' 我通过了 promise? Promise.resolve 将在您在then
中返回的所有内容上被隐式调用。【参考方案2】:
我将 Promise.settle 用于 sequelize.update,并且可以通过 _settledValueField 获取影响行数。
promise.push(...update...)
db.sequelize.Promise.settle(promise).then(function (allresult)
var affectcnt = 0
allresult.forEach(function (singlecnt)
if (undefined !== singlecnt._settledValueField[1])
affectcnt += parseInt(singlecnt._settledValueField[1])
)
不幸的是,它仅适用于更新。
【讨论】:
它看起来像部分答案。请尝试将其合并为完整的答案【参考方案3】:您可以使用 sequelize 在数据库中插入数组。您想更改模型,如下所示。我正在尝试通过数组在数据库中添加多种语言。
language: type: DataTypes.STRING,
allowNull: false,
get()
return this.getDataValue('language').split(';')
,
set(val)
this.setDataValue('language',Array.isArray(val) ? val.join(','):val);
【讨论】:
以上是关于使用 Sequelize 在项目数组上创建/更新的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Sequelize + PostgreSQL 将项目附加到数组值