web-dev-qa-db-fra.com

Sequelize: comment faire une condition WHERE sur une table jointe avec une jointure externe gauche

Mon modèle de base de données est le suivant:
Un employé conduit un ou zéro véhicule
Un véhicule peut être conduit par un ou plusieurs employés
Un véhicule a un type de modèle qui nous indique entre autres le type de carburant.

Picture of database diagram

Je voudrais que me chercher tous les employés où ils ne conduisent pas de véhicule, ou s'ils le font, alors le véhicule n'est pas diesel.
Donc, VehicleID est nul OR Vehicle.VehicleModel.IsDiesel = false

Mon code actuel est le suivant:

var employee = sequelize.define('employee', {
    ID: Sequelize.INTEGER,
    VehicleID: Sequelize.INTEGER
});

var vehicle = sequelize.define('vehicle', {
    ID: Sequelize.INTEGER,
    ModelID: Sequelize.INTEGER
});

var vehicleModel = sequelize.define('vehicleModel', {
    ID: Sequelize.INTEGER,
    IsDiesel: Sequelize.BOOLEAN
});

employee.belongsTo(vehicle);
vehicle.belongsTo(vehicleModel);

Si je lance ce qui suit:

options.include = [{
    model: model.Vehicle,
    attributes: ['ID', 'ModelID'],
        include: [
        {
            model: model.VehicleModel,
            attributes: ['ID', 'IsDiesel']
        }]
}];

employee
 .findAll(options)
 .success(function(results) {
     // do stuff
 });

Sequelize fait une jointure externe gauche pour obtenir les tables incluses. J'ai donc des employés qui conduisent des véhicules et qui ne le font pas.
Dès que j'ajoute un où à mes options:

options.include = [{
    model: model.Vehicle,
    attributes: ['ID', 'ModelID'],
    include: [
        {
            model: model.VehicleModel,
            attributes: ['ID', 'IsDiesel']
            where: {
                IsDiesel: false
            }
        }]
}];

Sequelize fait maintenant une jointure interne pour obtenir les tables incluses.
Cela signifie que je n'ai que des employés qui conduisent un véhicule et le véhicule n'est pas diesel. Les employés qui ne conduisent pas de véhicule sont exclus.

Fondamentalement, j'ai besoin d'un moyen de dire à Sequelize de faire une jointure externe gauche et en même temps d'avoir une condition where qui indique que la colonne de la table jointe est fausse ou nulle.

MODIFIER:

Il s'avère que la solution consistait à utiliser required: false, comme ci-dessous:

options.include = [{
    model: model.Vehicle,
    attributes: ['ID', 'ModelID'],
    include: [
        {
            model: model.VehicleModel,
            attributes: ['ID', 'IsDiesel']
            where: {
                IsDiesel: false
            },
            required: false
        }],
    required: false

}];

J'avais déjà essayé de mettre le premier "requis: faux" mais j'ai manqué de mettre celui intérieur. Je pensais que cela ne fonctionnait pas, alors j'ai abandonné cette approche. La réponse de Dajalmar Gutierrez m'a fait réaliser que j'avais besoin des deux pour que cela fonctionne.

17
Steve

Lorsque vous ajoutez une clause where, sequelize ajoute automatiquement une required: true à votre code.

Ajout required: false à votre segment d'inclusion devrait résoudre le problème

Remarque: vous devez vérifier ce problème iss4019

13
Dajalmar Gutierrez

Chargement avide

Lorsque vous récupérez des données de la base de données, il y a de fortes chances que vous souhaitiez également obtenir les associations avec la même requête - cela s'appelle chargement avide . L'idée de base derrière cela est l'utilisation de l'attribut include lorsque vous appelez find ou findAll. lorsque vous définissez

requis: faux

ça ira

LEFT OUTER JOIN

quand

requis: vrai

ça ira

INNER JOIN

pour plus de détails docs.sequelizejs eager-loading

5
Adiii