PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Les associations dans sequelize ne fonctionnent pas comme prévu

Il y a de nombreux problèmes. Je vais essayer de les aborder progressivement.

1) Modèles Par défaut, si vous ne déclarez pas de primaryKey , puis sequelize ajoute automatiquement un id colonne pour vous. Ainsi legId n'est pas une colonne utile.

De plus, si vous associez un modèle, le foreignKey la référence est ajoutée pour vous, donc pawId ne doit pas être déclaré.

Ainsi Legs.js doit être modifié en :

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
}

Ce qui précède me donne les colonnes suivantes dans pgAdmin :

2) Associations

L'association suivante n'a pas de sens et devrait provoquer une erreur :

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

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

Chaque Leg devrait avoir une Paw , et donc je suggère ce qui suit :

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) Clés étrangères

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

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

4) Chargement impatient

Lors du chargement rapide d'associations imbriquées, vous devez include leur. Vous devez également utiliser as alias correspondant à vos associations de modèles :

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

En utilisant toute cette configuration et la requête ci-dessus, j'obtiens :

[
  {
    "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

Comme il s'agit évidemment d'une configuration d'entraînement, vous pouvez modifier Paw être un belongsToMany relation (peut-être avez-vous des chats siamois par la patte ?) comme suit :

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

Ce serait la bonne façon d'implémenter ce que vous avez initialement essayé avec

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