Подтвердить что ты не робот

Как сделать объединение запросов с помощью Sequelize на Node.js

Я использую sequelize ORM; все замечательно и чисто, но у меня была проблема, когда я использую его с запросами join. У меня две модели: пользователи и сообщения.

var User = db.seq.define('User',{
    username: { type: db.Sequelize.STRING},
    email: { type: db.Sequelize.STRING},
    password: { type: db.Sequelize.STRING},
    sex : { type: db.Sequelize.INTEGER},
    day_birth: { type: db.Sequelize.INTEGER},
    month_birth: { type: db.Sequelize.INTEGER},
    year_birth: { type: db.Sequelize.INTEGER}

});

User.sync().success(function(){
    console.log("table created")
}).error(function(error){
    console.log(err);
})


var Post = db.seq.define("Post",{
    body: { type: db.Sequelize.TEXT },
    user_id: { type: db.Sequelize.INTEGER},
    likes: { type: db.Sequelize.INTEGER, defaultValue: 0 },

});

Post.sync().success(function(){
    console.log("table created")
}).error(function(error){
    console.log(err);
})

Мне нужен запрос, который отвечает сообщением с информацией пользователя, который сделал это. В исходном запросе я получаю следующее:

db.seq.query('SELECT * FROM posts, users WHERE posts.user_id = users.id ').success(function(rows){
            res.json(rows);
        });

Мой вопрос в том, как изменить код для использования стиля ORM вместо SQL-запроса?

4b9b3361

Ответ 1

User.hasMany(Post, {foreignKey: 'user_id'})
Post.belongsTo(User, {foreignKey: 'user_id'})

Post.find({ where: { ...}, include: [User]})

Который даст тебе

SELECT
  'posts'.*,
  'users'.'username' AS 'users.username', 'users'.'email' AS 'users.email',
  'users'.'password' AS 'users.password', 'users'.'sex' AS 'users.sex',
  'users'.'day_birth' AS 'users.day_birth',
  'users'.'month_birth' AS 'users.month_birth',
  'users'.'year_birth' AS 'users.year_birth', 'users'.'id' AS 'users.id',
  'users'.'createdAt' AS 'users.createdAt',
  'users'.'updatedAt' AS 'users.updatedAt'
FROM 'posts'
  LEFT OUTER JOIN 'users' AS 'users' ON 'users'.'id' = 'posts'.'user_id';

Приведенный выше запрос может показаться немного сложным по сравнению с тем, что вы опубликовали, но в основном он просто создает псевдонимы для всех столбцов таблицы пользователей, чтобы убедиться, что они возвращаются в правильную модель при возврате и не смешиваются с моделью публикаций.

Помимо этого вы заметите, что он выполняет JOIN вместо выбора из двух таблиц, но результат должен быть одинаковым

Дальнейшее чтение:

Ответ 2

Хотя принятый ответ не является технически неправильным, он не отвечает ни на исходный вопрос, ни на последующий вопрос в комментариях, что я и искал здесь. Но я понял это, так что здесь идет.

Если вы хотите найти все сообщения с пользователями (и только с пользователями), где SQL будет выглядеть так:

SELECT * FROM posts INNER JOIN users ON posts.user_id = users.id

Что семантически то же самое, что и оригинальный SQL OP:

SELECT * FROM posts, users WHERE posts.user_id = users.id

тогда это то, что вы хотите:

Posts.findAll({
  include: [{
    model: User,
    required: true
   }]
}).then(posts => {
  /* ... */
});

Установка значения true является ключом к созданию внутреннего соединения. Если вы хотите левое внешнее объединение (где вы получаете все сообщения, независимо от того, был ли там пользователь связан), то измените обязательное значение на ложное или оставьте его отключенным, поскольку по умолчанию:

Posts.findAll({
  include: [{
    model: User,
//  required: false
   }]
}).then(posts => {
  /* ... */
});

Если вы хотите найти все сообщения, принадлежащие пользователям, чей год рождения - 1984, вам нужно:

Posts.findAll({
  include: [{
    model: User,
    where: {year_birth: 1984}
   }]
}).then(posts => {
  /* ... */
});

Обратите внимание, что по умолчанию требуется true, как только вы добавите предложение where в.

Если вам нужны все сообщения, независимо от того, подключен ли пользователь, но если есть пользователь, то только те, которые родились в 1984 году, добавьте обязательное поле обратно в:

Posts.findAll({
  include: [{
    model: User,
    where: {year_birth: 1984}
    required: false,
   }]
}).then(posts => {
  /* ... */
});

Если вам нужны все сообщения с именем "Sunshine" и только если они принадлежат пользователю, родившемуся в 1984 году, вы должны сделать следующее:

Posts.findAll({
  where: {name: "Sunshine"},
  include: [{
    model: User,
    where: {year_birth: 1984}
   }]
}).then(posts => {
  /* ... */
});

Если вам нужны все сообщения с именем "Sunshine" и только если они принадлежат пользователю, родившемуся в том же году, который соответствует атрибуту post_year в сообщении, вы должны сделать это:

Posts.findAll({
  where: {name: "Sunshine"},
  include: [{
    model: User,
    where: ["year_birth = post_year"]
   }]
}).then(posts => {
  /* ... */
});

Я знаю, что не имеет смысла, чтобы кто-то делал посты в год, когда они родились, но это всего лишь пример. :)

Я понял это (в основном) из этого документа:

Ответ 3

Model1.belongsTo(Model2, { as: 'alias' })

Model1.findAll({include: [{model: Model2  , as: 'alias'  }]},{raw: true}).success(onSuccess).error(onError);

Ответ 4

В моем случае я сделал следующее. В UserMaster userId - это PK, а в UserAccess userId - это FK UserMaster

UserAccess.belongsTo(UserMaster,{foreignKey: 'userId'});
UserMaster.hasMany(UserAccess,{foreignKey : 'userId'});
var userData = await UserMaster.findAll({include: [UserAccess]});