Node.js'de Sequelize kullanarak birleştirme sorguları nasıl yapılır


104

ORM devamı kullanıyorum; her şey harika ve temiz ama joinsorgularla kullandığımda bir sorun yaşadım . İki modelim var: kullanıcılar ve gönderiler.

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);
})

Gönderiyi yapan kullanıcının bilgileriyle yanıt veren bir sorgu istiyorum. Ham sorguda şunu anlıyorum:

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

Sorum şu: SQL sorgusu yerine ORM stilini kullanmak için kodu nasıl değiştirebilirim?

Yanıtlar:


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

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

Sana verecek

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`;

Yukarıdaki sorgu, gönderdiklerinize kıyasla biraz karmaşık görünebilir, ancak temelde, döndürüldüklerinde doğru modele yerleştirildiklerinden ve gönderi modeliyle karıştırılmadıklarından emin olmak için yalnızca kullanıcılar tablosunun tüm sütunlarını takma ad kullanmaktır.

Bunun dışında iki tablodan seçmek yerine bir JOIN yaptığını fark edeceksiniz, ancak sonuç aynı olmalıdır

Daha fazla okuma:


7
Ya sadece 1984 doğumlu Kullanıcılara katılmak istersem? SQL'de SELECT * FROM posts JOIN users ON users.id = posts.user_id WHERE users.year_birth = 1984
şunları

1
Tüm bağlantılar ölü değil :-(
Manwal

1
Bu soru yanıtlanan bir soruda hiç yayınlandı mı?
theptrk

1
İkisine de ihtiyacımız var mı yoksa biri yeterli mi: User.hasMany (Post, {foreignKey: 'user_id'}) Post.belongsTo (Kullanıcı, {foreignKey: 'user_id'})
antew

1
@antew Sizi aradığınızda User.hasMany(Post), User nesnesine yöntemler / öznitelikler ekleyin ve sizi çağırdığınızda Post.belongsTo(User)Post sınıfına yöntemler ekleyin. Her zaman tek bir yönden (örn. User.getPosts ()) arıyorsanız, Post nesnesine herhangi bir şey eklemenize gerek yoktur. Ancak yöntemlerin her iki tarafta olması güzel.
Ryan Shillington

170

Kabul edilen cevap teknik olarak yanlış olmasa da, orijinal soruya veya yorumlarda takip edilen soruya cevap vermiyor, buraya aradığım şey buydu. Ama ben anladım, işte başlıyor.

Kullanıcıları olan (ve yalnızca kullanıcıları olanları) SQL'in aşağıdaki gibi görüneceği tüm Gönderileri bulmak istiyorsanız:

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

Bu, OP'nin orijinal SQLiyle semantik olarak aynı şeydir:

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

o zaman istediğin bu:

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

True için gerekli ayar, bir iç birleşim oluşturmanın anahtarıdır. Sol dış birleştirme istiyorsanız (bağlı bir kullanıcı olup olmadığına bakılmaksızın tüm Gönderileri aldığınız yer), gerekli olanı false olarak değiştirin veya varsayılan olduğundan bu seçeneği kapalı bırakın:

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

Doğum yılı 1984 olan kullanıcılara ait tüm Gönderileri bulmak istiyorsanız, şunları istersiniz:

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

Bir where cümlesi eklediğiniz anda gerekli değerinin varsayılan olarak doğru olduğunu unutmayın.

Eklenmiş bir kullanıcı olup olmadığına bakılmaksızın tüm Gönderileri istiyorsanız, ancak bir kullanıcı varsa, o zaman yalnızca 1984 doğumlu olanlar, gerekli alanı tekrar ekleyin:

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

Adı "Gün Işığı" olan tüm Gönderileri istiyorsanız ve yalnızca 1984 doğumlu bir kullanıcıya aitse, şunu yaparsınız:

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

Adın "Güneş Işığı" olduğu tüm Gönderileri istiyorsanız ve yalnızca gönderideki post_year özniteliğiyle eşleşen aynı yıl doğmuş bir kullanıcıya aitse, şunu yaparsınız:

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

Biliyorum, birinin doğdukları yıl bir görevde bulunmasının bir anlamı yok, ama bu sadece bir örnek - onunla devam et. :)

Bunu (çoğunlukla) bu belgeden anladım:


9
Çok teşekkür ederim, bu faydalı oldu
Neo

6
evet, harika cevap
duxfox--

öyleyse posts.user_id = users.iddevamında neyi temsil ediyor? teşekkürler
hanzichi

5
Bu cevap o kadar kapsamlı ki, Sequelize'nin belgesine bağlanmalıdır
Giorgio Andretti

2
Aradığım harika bir eğitim parçası Çok teşekkürler
Andrew Rayan

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

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

2

Benim durumumda aşağıdaki şeyi yaptım. UserMaster'da userId PK ve UserAccess'te userId UserMaster'ın FK'sidir.

UserAccess.belongsTo(UserMaster,{foreignKey: 'userId'});
UserMaster.hasMany(UserAccess,{foreignKey : 'userId'});
var userData = await UserMaster.findAll({include: [UserAccess]});
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.