Utiliser group by et participer à sequelize

j'ai deux tables sur une base de données PostgreSQL, contrats et paiements. Un contrat a 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;
};

j'aimerais faire la somme de 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 les paiements.id, parce que je devrais l'inclure dans mon agrégation ou groupe par fonctions, comme dit dans le message d'erreur que j'ai:

peut-être non manipulé SequelizeDatabaseError: erreur: colonne "paiements.id" doit apparaître dans le groupe par clause OU être utilisé dans une fonction agrégée

est-ce que je rate quelque chose ici ? Je suis la suite cette réponse mais même là Je ne comprends pas comment la requête SQL peut être valide.

19
demandé sur Community 2015-01-29 06:45:08

4 réponses

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 fait sur le modèle principal (infos dans c'github question).

Donc 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']
})
16
répondu syldor 2015-06-09 09:58:41

est la question que vous pourriez vouloir sélectionner à partir de payments et en joignant contracts plutôt que l'inverse?

1
répondu swifty 2015-03-03 08:37:49

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']
})
1
répondu Rahul Bhati 2015-03-03 10:51:44

group: ['contracts.id', 'payments.id']
1
répondu Calvintwr 2015-03-03 17:15:15