Я создаю две модели, первая — User
, а вторая — Portfolio
. Когда пользователь создает Portfolio
(где у пользователя может быть только один Portfolio
), я хочу, чтобы он имел ссылку на пользователя, который его создает, и каждый раз, когда данные этого пользователя извлекаются, я хотите, чтобы он также извлекал данные их портфолио, если таковые имеются.
Я пытаюсь использовать hasOne
для создания portfolio_id
внутри таблиц User
со скелетом, сгенерированным с помощью команды sequelize init
, но это не работает. Я не могу найти столбец с именем protfolio_id
, если не поместил его в файл миграции пользователей. Так должно быть?
Как мне проектировать модели? Должен ли я включать portfolio_id
в таблицы User
и включать user_id
в таблицу Portfolio
, или есть лучший способ сделать это?
И какой метод ассоциаций мне следует использовать, hasOne или ownTo?
1 ответ
Прежде всего убедитесь, что вы вызываете Model.associate
для каждой модели. Это запустит запросы для всех отношений.
Вы можете определить отношения в ассоциированном методе следующим образом:
// user.js (User Model definition)
module.exports = (sequelize, dataTypes) => {
const { STRING } = dataTypes
const User = sequelize.define("user", {
username: { type: STRING }
})
User.associate = models => {
User.hasOne(models.Portfolio, { foreignKey: "userId" }) // If only one portfolio per user
User.hasMany(models.Portfolio) // if many portfolios per user
}
return User
}
// portfolio.js (Portfolio Model definition)
module.exports = (sequelize, dataTypes) => {
const { STRING } = dataTypes
const Portfolio = sequelize.define("portfolio", {
portfolioName: { type: STRING }
})
Portfolio.associate = models => {
Portfolio.belongsTo(models.User, { foreignKey: "userId" })
}
return Portfolio
}
hasOne сохраняет внешний ключ в целевой модели. Таким образом, эта связь добавит внешний ключ userId
к модели Portfolio
.
belongsTo хранит ключ в текущей модели и ссылается на первичный ключ целевой модели. В этом случае Portfolio.belongsTo
добавит userId
в модель Portfolio
, которая будет ссылаться на первичный ключ модели User
.
Обратите внимание, что обе эти связи делают одно и то же: они добавляют идентификатор пользователя в модель портфеля. Лучше определить это в обеих моделях для вашего последнего варианта использования:
Я хочу, чтобы он имел ссылку на пользователя, который его создает, и каждый раз, когда данные этого пользователя извлекаются, я хочу, чтобы он также извлекал данные их портфолио, если таковые имеются.
Доступ к связанным моделям:
В дальнейшем извлечение связанной модели вместе с основной моделью называется Нетерпеливая загрузка. Подробнее об этом читайте здесь.
Теперь для вашего варианта использования, если вы хотите получить портфолио, если оно есть, при извлечении пользователя сделайте следующее:
var userWithPortfolio = await User.findAll({include: [models.Portfolio]};
// Or you may also use include: {all: true} to include all related models.
var userWithPortfolio = await User.findAll({include: {all: true}};
/*
Output:
userWithPortfolio = {
username: "xyz",
portfolio: {
portfolioName: "xyz"
}
}
*/
Похожие вопросы
Новые вопросы
node.js
Node.js — это основанная на событиях, неблокирующая, асинхронная среда выполнения ввода-вывода, использующая движок Google V8 JavaScript и библиотеку libuv. Он используется для разработки приложений, которые интенсивно используют возможность запуска JavaScript как на стороне клиента, так и на стороне сервера и, следовательно, выигрывают от возможности повторного использования кода и отсутствия переключения контекста.
user_id
в таблицеPortfolio
при выполненииsequelize db:migrate
? Или это не должно так работать, поэтому я должен вручную указать внешний ключ в файле миграции?sequelize.sync({force: true})
после вызова ассоциирования на всех моделях. Вызовsync({force: true})
удалит все таблицы и создаст их с нуля, используя новые определения. Если вы не хотите потерять данные, вам придется создайте миграцию для ассоциации, как показано в связанном постеPortfolio
уже естьuser_id
, который ссылается наid
в таблицеUser
, вам может потребоваться только перезапустить сервер.