J'ai deux tableaux sur une base de données PostgreSQL, des contrats et des paiements. Un contrat comporte plusieurs paiements.
J'ai les deux modèles suivants:
module.exports = function(sequelize, DataTypes) {
var contracts = sequelize.define('contracts', {
id: {
type: DataTypes.INTEGER,
autoIncrement: true
}
}, {
createdAt: false,
updatedAt: false,
classMethods: {
associate: function(models) {
contracts.hasMany(models.payments, {
foreignKey: 'contract_id'
});
}
}
});
return contracts;
};
module.exports = function(sequelize, DataTypes) {
var payments = sequelize.define('payments', {
id: {
type: DataTypes.INTEGER,
autoIncrement: true
},
contract_id: {
type: DataTypes.INTEGER,
},
payment_amount: DataTypes.INTEGER,
}, {
classMethods: {
associate: function(models) {
payments.belongsTo(models.contracts, {
foreignKey: 'contract_id'
});
}
}
});
return payments;
};
Je voudrais résumer tous les paiements effectués pour chaque contrat et j'ai utilisé cette fonction:
models.contracts.findAll({
attributes: [
'id'
],
include: [
{
model: models.payments,
attributes: [[models.sequelize.fn('sum', models.sequelize.col('payments.payment_amount')), 'total_cost']]
}
],
group: ['contracts.id']
})
Mais il génère la requête suivante:
SELECT "contracts"."id", "payments"."id" AS "payments.id", sum("payments"."payment_amount") AS "payments.total_cost"
FROM "contracts" AS "contracts"
LEFT OUTER JOIN "payments" AS "payments" ON "contracts"."id" = "payments"."contract_id" GROUP BY "contracts"."id";
Je ne demande pas de sélectionner paiements.id, car je devrais l'inclure dans mon agrégation ou grouper par fonctions, comme dit dans l'erreur que j'ai:
SequelizeDatabaseError éventuellement non gérée: erreur: la colonne "paiements.id" doit apparaître dans la clause GROUP BY ou être utilisée dans une fonction d'agrégation
Est-ce que j'ai râté quelque chose ? Je suis cette réponse mais même là, je ne comprends pas comment la requête SQL peut être valide.
Ce problème a été corrigé sur Sequelize 3.0.1, la clé primaire des modèles inclus doit être exclue avec
attributes: []
et l'agrégation doit être faite sur le modèle principal (infos dans ce problème github ).
Ainsi pour mon cas d'utilisation, le code est le suivant
models.contracts.findAll({
attributes: ['id', [models.sequelize.fn('sum', models.sequelize.col('payments.payment_amount')), 'total_cost']],
include: [
{
model: models.payments,
attributes: []
}
],
group: ['contracts.id']
})
Essayer
group: ['contracts.id', 'payments.id']
Le problème que vous voudrez peut-être sélectionner parmi payments
et rejoindre contracts
plutôt que l'inverse?
Pouvez-vous écrire votre fonction comme
models.contracts.findAll({
attributes: [
'models.contracts.id'
],
include: [
{
model: models.payments,
attributes: [[models.sequelize.fn('sum', models.sequelize.col('payments.payment_amount')), 'total_cost']]
}
],
group: ['contracts.id']
})