Обновление атрибутов в связанных моделях с использованием Sequelize
Можно ли обновлять атрибуты как для родительской модели, так и для связанных моделей всего за один раз? У меня возникли проблемы с его работой, и я не смог найти никаких примеров. Я не уверен, что что-то не так с моим кодом или если оно не предназначено для работы, как я ожидал бы. Я попытался добавить onUpdate: 'cascade' в мое определение hasMany, но это ничего не делало.
Модели:
module.exports = function( sequelize, DataTypes ) {
var Filter = sequelize.define( 'Filter', {
id : {
type : DataTypes.INTEGER,
autoIncrement : true,
primaryKey : true
},
userId : DataTypes.INTEGER,
filterRetweets : DataTypes.BOOLEAN,
filterContent : DataTypes.BOOLEAN
},
{
tableName : 'filter',
timestamps : false
}
);
var FilteredContent = sequelize.define( 'FilteredContent', {
id : {
type : DataTypes.INTEGER,
autoIncrement : true,
primaryKey : true
},
filterId : {
type : DataTypes.INTEGER,
references : "Filter",
referenceKey : "id"
},
content : DataTypes.STRING
},
{
tableName : "filteredContent",
timestamps : false
}
);
Filter.hasMany( FilteredContent, { onUpdate : 'cascade', as : 'filteredContent', foreignKey : 'filterId' } );
sequelize.sync();
return {
"Filter" : Filter,
"FilteredContent" : FilteredContent
};
}
Извлечение фильтра и попытка обновления атрибута на связанном объекте FilteredContent:
Filter.find({ where: { id: 3 },
include: [ { model : FilteredContent, as : 'filteredContent' } ]
}).success ( function( filter ) {
var filteredContent = FilteredContent.build( {
filterId : filter.id,
id : 2,
content : 'crap'
});
filter.save();
});
Это приводит только к атрибутам в обновляемом объекте Filter. Как получить его, чтобы обновить атрибуты в FilteredContent?
Кроме того, требуется ли sequelize.sync() после определения моих моделей? Я не понимаю, что именно он должен делать. Я могу получить свой объект с ассоциациями без него. Я добавил его в свой код в отчаянии, чтобы получить обновления, но я не уверен, действительно ли это необходимо.
Спасибо
Ответы
Ответ 1
На ваш вопрос:
Когда вы с нетерпением загружаете FilteredContent (используя include), экземпляр модели уже построен, поэтому нет причин для вызова build
. Что-то вроде этого должно делать то, что вы хотите:
Filter.find({
where: { id: 3 },
include: [ { model : FilteredContent, as : 'filteredContent' } ]
}).then ( function( filter ) {
return filter.filteredContent[0].updateAttributes({
content: 'crap'
})
}).then(function () {
// DONE! :)
});
Несколько указателей на код, который вы опубликовали в целом:
- sequelize.sync создает таблицы базы данных для ваших моделей, если они еще не существуют. Это не требуется для того, что вы хотите сделать, если ваши таблицы уже существуют.
- sequelize.sync - это асинхронная операция, поэтому выполнение secelize.sync без привязки обратного вызова не рекомендуется. Кроме того, похоже, что вы выполняете синхронизацию в определении модели - вы должны делать это только один раз, предпочтительно в том месте, где вы определяете свои модели.
- Похоже, вы определяете несколько моделей в одном файле - вы должны определять только один в каждом файле. Ассоциации можно настроить, выполнив sequelize.import([путь к модели фильтра) в файле FilterContent или сделав все ассоциации в месте импорта своих моделей в ваше приложение.
изменить ответ на ваш комментарий:
Вы не можете выполнить один вызов функции, который будет обновлять фильтр и фильтровать содержимое, но вам также не нужно делать обновления в последовательности. Вы можете выпустить все команды обновления, не дожидаясь их завершения.
Filter.find({
where: { id: 3 },
include: [ { model : FilteredContent, as : 'filteredContent' } ]
}).then ( function( filter ) {
return Promise.all([
filter.updateAttributes({}),
filter.filteredContent.map(fc => fc.updateAttributes({}))
]);
}).spread(function (filter, filteredContents) {
})
Таким образом, все запросы будут выполняться параллельно, и ваша функция будет вызываться, когда все они будут завершены. Обратите внимание, что я использовал spread
здесь, чтобы вернуть массив из Promise.all
в отдельные аргументы.
Ответ 2
Здравствуйте, @Jan Aagaard Meier может помочь мне, моя вторая и обновленная таблица следует моему коду, мне действительно нужно решить эту проблему, что я могу делать неправильно?
Мои отношения между двумя профилями и таблицами модулей профиля Модуль профиля имеет ключ profileId, где он связан с ProfileId Profile, а у меня есть поле ModuleId:
models.Profile_Module.belongsTo(models.Profile, { foreignKey: "profileId" });
models.Profile.hasMany(models.Profile_Module, {
foreignKey: "profileId",
sourceKey: "profileId",
as: "pr"
});
Мой метод кода:
async function update(data, profileId) {
models.Profile.findOne({
where: {
profileId: profileId
},
attributes: {
exclude: ["customerId", "profileDeletedUser", "profileDeletedDate"]
},
raw: true,
include: [
{
model: models.Profile_Module,
required: true,
as: "pr"
}
]
})
.then(function(prof) {
return Promise.all([
models.Profile.update(
{
profileName: data.profileName,
profileDescription: data.profileDescription
},
{
where: { profileId: profileId }
}
),
models.pr.map(fc =>
fc.update(
{ moduleId: data.modules.moduleId },
{ where: { profileId: profileId } }
)
)
]);
})
.then(console.log)
.catch(console.log);
// .spread(function(prof, pr) {
// return filter;
// });
}
Тело моего запроса:
{
"profileName": "Teste",
"profileDescription": "Teste profile description",
"modules":[
{
"moduleId":1
},
{
"moduleId":2
}
]
}