Использование group by и объединение в sequelize

У меня есть две таблицы в базе данных PostgreSQL, контрактах и ​​платежах. В одном контракте сделано несколько платежей.

У меня есть две следующие модели:

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

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

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']
})

Но он генерирует следующий запрос:

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

Я не прошу выбрать payments.id, потому что мне пришлось бы включать его в мою агрегацию или группу по функциям, как сказано в ошибке, которую я имею:

Возможно необработанное SequelizeDatabaseError: ошибка: столбец "payments.id" должен появиться в предложении GROUP BY или использоваться в агрегатной функции

Я что-то упустил? Я следую этому ответу, но даже там я не понимаю, как запрос SQL может быть действительным.

Ответы

Ответ 1

Эта проблема была исправлена ​​в Sequelize 3.0.1, первичный ключ включенных моделей должен быть исключен с помощью

attributes: []

и агрегация должна быть выполнена на основной модели (информация в этой проблеме github).

Таким образом, для моего варианта использования код следующий

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']
})

Ответ 2

Это проблема, которую вы, возможно, захотите выбрать из payments и присоединяться contracts, а не наоборот?

Ответ 3

Можете ли вы написать свою функцию как

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']
})

Ответ 4

Try

group: ['contracts.id', 'payments.id']