2016-12-06 36 views
0

我有一個場景,我試圖查詢父表(文檔)與兩個相關聯的表(參考&用戶),這兩個表彼此沒有關係,但與父表。在SQL中,這個查詢看起來像這樣正確輸出我要尋找的數據:與兩個表的序列化嵌套關聯

select * 
from `document` 
left join `user` 
on `document`.`user_id` = `user`.`user_id` 
left join `reference` 
on `document`.`reference_id` = `reference`.`reference_id` 
where `user`.`organization_id` = 1; 

然而,嵌套協會在分層爲了把爲了使查詢工作。由於嵌套關聯不相互關聯,我得到一個關聯錯誤。我怎樣才能避免這個錯誤? required: false會對此有影響嗎?

models.Document.findAll({ 
    order: 'documentDate DESC', 
    include: [{ 
    model: models.User, 
    where: { organizationId: req.user.organizationId }, 
    include: [{ 
     model: models.Reference, 
    }] 
    }], 
}) 

錯誤

Unhandled rejection Error: reference is not associated to user!

協會

Document

associate: function(db) { 
    Document.belongsTo(db.User, {foreignKey: 'user_id'}), 
    Document.belongsTo(db.Reference, { foreignKey: 'reference_id'});; 
} 

Reference

associate: function(db){ 
    Reference.hasMany(db.Document, { foreignKey: 'reference_id' }); 
} 

如果我只是連鎖查詢呢?

+0

它看起來像指定'underscored:true',但使用cameCase名稱:'organization_id'對'organizationId'例如。 – doublesharp

回答

1

如果您想複製您的查詢(儘可能接近),請使用以下查詢。請注意,用戶include上的where僅用於刪除Document.user_idUser.organization_id不匹配的匹配項,但仍會返回Document。如果您想省略User.organization_id不匹配的文檔,請使用required: true

User <- Document -> Reference

models.Document.findAll({ 
    // this is an array of includes, don't nest them 
    include: [{ 
    model: models.User, 
    where: { organization_id: req.user.organization_id }, // <-- underscored HERE 
    required: true, // <-- JOIN to only return Documents where there is a matching User 
    }, 
    { 
    model: models.Reference, 
    required: false, // <-- LEFT JOIN, return rows even if there is no match 
    }], 
    order: [['document_date', 'DESC']], // <-- underscored HERE, plus use correct format 
}); 
+0

這正是我所期待的!我一直在試圖弄清楚如何連接與父表關聯的多個表,但不在一起並解決了這個問題。你怎麼知道在包含數組中嵌套而不是在第一個包含另一個包含?我不相信我曾經在文檔或任何社區答案中找到過。 – cphill

+0

這取決於您的數據模型。就像我之前提到的(爲什麼我的第一個答案不正確),當你嵌套它們時,你將關係類型改爲'Document-> User-> Reference',當你真的想要'Document-> User' +'Document-> Reference '。 – doublesharp

0

錯誤提示User型號與Reference型號沒有關聯,但在描述中只有DocumentReference型號的定義。您在查詢時使用include選項加入這些表格,因此您必須確保它們已關聯。您在技術上不需要foreignKey,您可以指定默認值。

添加Reference->User協會

associate: function(db) { 
    // belongsTo()? maybe another relationship depending on your data model 
    Reference.belongsTo(db.User, {foreignKey: 'user_id'}); 

    Reference.hasMany(db.Document, { foreignKey: 'reference_id' }); 
} 

它也像你可能設置在模型中定義underscored: true,使您的查詢應該反映出這一點。此外,如果您想執行LEFT JOIN,則需要在include上指定required: false,否則爲常規JOIN,並且您只會在include d模型中找回匹配的行。您也正在使用錯誤的order格式,它應該是一個值數組,並且按model.document_date DESC排序,您應該使用order: [['document_date', 'DESC']]

正確的查詢參數

models.Document.findAll({ 
    order: [['document_date', 'DESC']], // <-- underscored HERE, plus use correct format 
    include: [{ 
    model: models.User, 
    where: { organization_id: req.user.organization_id }, // <-- underscored HERE 
    required: false, // <-- LEFT JOIN 
    include: [{ 
     model: models.Reference, 
     required: false, // <-- LEFT JOIN 
    }] 
    }], 
}); 

如果您仍然有問題,嘗試在你的Sequelize連接設置logging: console.log啓用日誌記錄,會告訴你這是在控制檯運行的所有查詢。

+0

我欣賞詳細的評論,並注意到我從來沒有添加關於用戶模型的細節。我之所以將它排除在簡要參考之外是因爲該模型沒有與其他兩個表(文檔和參考)有關。我的問題是,如果沒有外鍵就沒有關聯表格,從而失去了什麼樣的關聯應該是什麼目的?表與FK之間的關係?原始查詢是否會成爲更好的路由,因爲引用與用戶沒有直接關係? – cphill

+0

您的查詢反映該關聯是'文檔 - >用戶 - >參考'。 – doublesharp

+0

你的意思是查詢'文檔 - >用戶'和'文檔 - >參考「? – doublesharp

0

在我看來,你的問題可能是協會,試圖鏈接回你的主鍵上的文檔,而不是列「USER_ID」和「REFERENCE_ID」。你沒有發佈表格屬性,所以我可能已經明白這個錯誤。

關於文件的關聯是好的。

文件

associate: function(db) { 
    Document.belongsTo(db.User, {foreignKey: 'user_id'}), //key in documents 
    Document.belongsTo(db.Reference, { foreignKey: 'reference_id'}); //key in documents 
} 

用戶

associate: function(db) { 
    User.belongsTo(db.Document, { 
    foreignKey: 'id', //Key in User 
    targetKey: 'user_id' //Key in Documents 
    }), 
} 

參考

associate: function(db) { 
    Reference.belongsTo(db.Document, { 
     foreignKey: 'id',   //Key in reference 
     targetKey: 'reference_id' //Key in Documents 
    }), 
} 

此外

對於debbuging考慮使用記錄,以便你可以看到查詢。

var sequelize = new Sequelize('database', 'username', 'password', { 
    logging: console.log 
    logging: function (str) { 
     // do your own logging 
    } 
});