sql >> Base de Datos >  >> RDS >> PostgreSQL

Las asociaciones en Sequelize no funcionan según lo previsto

Hay muchos problemas. Intentaré abordarlos gradualmente.

1) Modelos De forma predeterminada, si no declara una primaryKey , luego secuencial agrega automáticamente un id columna para ti. Así legId no es una columna útil.

Además, si asocia un modelo, la foreignKey la referencia se agrega para usted, por lo tanto, pawId no debe ser declarado.

Así Legs.js debe modificarse a:

module.exports = (sequelize, DataTypes) => {
  var Leg = sequelize.define('Leg', {
    originalValue: DataTypes.JSON,
    newValue: DataTypes.JSON,
    objectId: DataTypes.INTEGER // not entirely sure what this is 
  })
  Leg.associate = function (models) {
    // associations
  }
  return Leg
}

Lo anterior me da las siguientes columnas en pgAdmin :

2) Asociaciones

La siguiente asociación no tiene sentido y debería causar un error:

Leg.hasOne(Paw)
Paw.hasMany(Leg)

Unhandled rejection Error: Cyclic dependency found. Legs is dependent of itself.
Dependency chain: Legs -> Paws => Legs

Cada Leg debe tener una Paw , y por lo tanto sugiero lo siguiente:

Leg.associate = function (models) {
  // Leg.belongsTo(models.Cat)
  Leg.hasOne(models.Paw, {
    foreignKey: 'pawId',
    as: 'paw'
  })
}

Paw.associate = function (models) {
  Paw.belongsTo(models.Leg, {
    as: 'leg' // note this changed to make more sense
    foreignKey: 'pawId'
  })
}

3) Claves foráneas

Leg.belongsTo(models.Cat, {
  foreignKey: 'catId', // this should match
  onDelete: 'CASCADE'
})

Cat.hasMany(models.Leg, {
  foreignKey: 'catId', // this should match
  as: 'legs'
})

4) Carga ansiosa

Cuando desee cargar asociaciones anidadas, debe include a ellos. También debe usar as alias que coincida con sus asociaciones modelo:

Cat.findAll({
  include: [{
    model: Leg,
    as: 'legs', // Cat.legs 
    include: [{
      model: Paw,
      as: 'paw' // Leg.paw instead of Leg.pawId
    }]
  }]
})

Usando toda esta configuración y la consulta anterior, obtengo:

[
  {
    "id": 1,
    "userId": "1",
    "createdAt": "2018-04-15T11:22:59.888Z",
    "updatedAt": "2018-04-15T11:22:59.888Z",
    "legs": [
      {
        "id": 1,
        "originalValue": null,
        "newValue": null,
        "objectId": null,
        "createdAt": "2018-04-15T11:22:59.901Z",
        "updatedAt": "2018-04-15T11:22:59.901Z",
        "catId": 1,
        "paw": {
          "id": 1,
          "pawType": null,
          "createdAt": "2018-04-15T11:22:59.906Z",
          "updatedAt": "2018-04-15T11:22:59.906Z",
          "pawId": 1
        }
      }
    ]
  }
]

Extra

Debido a que esta es obviamente una configuración de práctica, podría modificar Paw ser un belongsToMany relación (¿quizás has unido gatos por la pata?) de la siguiente manera:

Paw.associate = function (models) {
  Paw.belongsToMany(models.Leg, {
    foreignKey: 'pawId',
    through: 'PawLegs  // a through join table MUST be defined
  })
}

Esta sería la forma correcta de implementar lo que intentaste inicialmente con

Leg.hasOne(paw)
paw.hasMany(leg)