SequelizeJS渴望加载两个相同的N:M模型,一个返回数据,另一个不返回

时间:2019-02-17 17:47:20

标签: mysql sql node.js sequelize.js

我有一个模型Link和另外两个模型OverlayTracker。两者都与Link模型有很多关系。数据在MySQL数据库中。

OverlayTrackerLink使用相同的关联,但是当我尝试使用顺序查询来加载它们时,Tracker的值始终为null(返回作为空数组)。

例如:

考虑此示例查询。

const result = await Link.findAndCountAll({
        where: {
            userId: req.user.id
        },
        limit: limit,
        offset: offset,
        order: [
            ['createdAt', 'DESC']
        ],
        include: [
            {model: Tracker, as: 'trackers'},
            {model: Overlay, as: 'overlays'}
        ]
    });

返回的结果正确包含overlays,但是trackers始终为空数组。我真的很困惑,因为两种模型的关联性都相同。

模型

Link.js

'use strict';

module.exports = (sequelize, DataTypes) => {
  const Link = sequelize.define('Link', {
    name: DataTypes.STRING,
    // ... removed for simplicity
    }
  }, {
    freezeTableName: true,
    tableName: 'links'
  });

  Link.associate = function(models) {
    // associations can be defined here
    Link.belongsTo(models.User, {
      as: 'user',
      foreignKey: 'userId'
    });

    Link.belongsToMany(models.Overlay, {
      as: 'overlays',
      through: models.LinkOverlays,
      foreignKey: 'linkId',
      targetKey: 'id',
    });

    Link.belongsToMany(models.Tracker, {
      as: 'trackers',
      through: models.LinkTrackers,
      foreignKey: 'trackerId',
      targetKey: 'id',
    });
  };

  return Link;
};

Overlay.js

'use strict';

module.exports = (sequelize, DataTypes) => {

  const Overlay = sequelize.define('Overlay', {
    name: DataTypes.STRING(100),
    // ... removed for simplicity  
  }, {
    freezeTableName: true,
    tableName: 'overlays'
  });

  Overlay.associate = function(models) {
    // associations can be defined here
    Overlay.belongsTo(models.User, {
      foreignKey: 'userId'
    });

    Overlay.belongsToMany(models.Link, {
      as: 'links',
      through: models.LinkOverlays,
      foreignKey: 'overlayId',
      targetKey: 'id'
    });
  };

  return Overlay;
};

Tracker.js

'use strict';

module.exports = (sequelize, DataTypes) => {

  const Tracker = sequelize.define('Tracker', {
    name: DataTypes.STRING(100),
    // ...
  }, {
    freezeTableName: true,
    timestamps: false,
    tableName: 'trackers'
  });

  Tracker.associate = function(models) {

    Tracker.belongsTo(models.User, {
      foreignKey: 'userId'
    });

    Tracker.belongsToMany(models.Link, {
      as: 'links',
      through: models.LinkTrackers,
      foreignKey: 'trackerId',
      targetKey: 'id'
    });
  };

  return Tracker;
};

观察:

对于两个关联的模型,创建的SQL查询似乎也相同。这是给定查询的结果SQL

 SELECT `Link`.*,
       `trackers`.`id`                      AS `trackers.id`,
       `trackers`.`createdat`               AS `trackers.createdAt`,
       `trackers`.`name`                    AS `trackers.name`,
       `trackers`.`vendor`                  AS `trackers.vendor`,
       `trackers`.`vendortrackerid`         AS `trackers.vendorTrackerId`,
       `trackers`.`userid`                  AS `trackers.userId`,
       `trackers->LinkTrackers`.`linkid`    AS `trackers.LinkTrackers.linkId`,
       `trackers->LinkTrackers`.`trackerid` AS `trackers.LinkTrackers.trackerId`
       ,
       `overlays`.`id`                      AS `overlays.id`,
       `overlays`.`name`                    AS `overlays.name`,
       `overlays`.`type`                    AS `overlays.type`,
       `overlays`.`config`                  AS `overlays.config`,
       `overlays`.`userid`                  AS `overlays.userId`,
       `overlays`.`createdat`               AS `overlays.createdAt`,
       `overlays`.`updatedat`               AS `overlays.updatedAt`,
       `overlays->LinkOverlays`.`linkid`    AS `overlays.LinkOverlays.linkId`,
       `overlays->LinkOverlays`.`overlayid` AS `overlays.LinkOverlays.overlayId`
FROM   (SELECT `Link`.`id`,
               `Link`.`name`,
               `Link`.`originalurl`,
               `Link`.`code`,
               `Link`.`type`,
               `Link`.`userid`,
               `Link`.`hitcount`,
               `Link`.`opengraph`,
               `Link`.`createdat`,
               `Link`.`updatedat`
        FROM   `links` AS `Link`
        WHERE  `Link`.`userid` = 1
        ORDER  BY `Link`.`createdat` DESC
        LIMIT  0, 10) AS `Link`
       LEFT OUTER JOIN ( `link_trackers` AS `trackers->LinkTrackers`
                         INNER JOIN `trackers` AS `trackers`
                                 ON `trackers`.`id` =
                                    `trackers->LinkTrackers`.`trackerid`)
                    ON `Link`.`id` = `trackers->LinkTrackers`.`trackerid`
       LEFT OUTER JOIN ( `link_overlays` AS `overlays->LinkOverlays`
                         INNER JOIN `overlays` AS `overlays`
                                 ON `overlays`.`id` =
                                    `overlays->LinkOverlays`.`overlayid`)
                    ON `Link`.`id` = `overlays->LinkOverlays`.`linkid`
ORDER  BY `Link`.`createdat` DESC;  

更多信息

下面是两个关系表模型

LinkOverlays.js

'use strict';
module.exports = (sequelize, DataTypes) => {

  const LinkOverlays = sequelize.define('LinkOverlays', {
    linkId: {
      type: DataTypes.INTEGER,
      primaryKey: true,
      unique: 'linkIdOverlayIdComposite'
    },
    overlayId: {
      type: DataTypes.INTEGER,
      primaryKey: true,
      unique: 'linkIdOverlayIdComposite'
    }
  }, {
    freezeTableName: true,
    timestamps: false,
    tableName: 'link_overlays'
  });

  LinkOverlays.associate = function(models) {

    // associations can be defined here
    LinkOverlays.belongsTo(models.Link, {
      foreignKey: 'linkId',
      through: models.LinkOverlays,
      targetKey: 'id'
    });

    // associations can be defined here
    LinkOverlays.belongsTo(models.Overlay, {
      foreignKey: 'overlayId',
      through: models.LinkOverlays,
      targetKey: 'id'
    });

  };

  return LinkOverlays;
};

LinkTrackers.js

'use strict';
module.exports = (sequelize, DataTypes) => {

  const LinkTrackers = sequelize.define('LinkTrackers', {
    linkId: {
      type: DataTypes.INTEGER,
      primaryKey: true,
      unique: 'linkIdTrackerIdComposite'
    },
    trackerId: {
      type: DataTypes.INTEGER,
      primaryKey: true,
      unique: 'linkIdTrackerIdComposite'
    }
  }, {
    freezeTableName: true,
    timestamps: false,
    tableName: 'link_trackers'
  });

  LinkTrackers.associate = function(models) {

    LinkTrackers.belongsTo(models.Link, {
      foreignKey: 'linkId',
      through: models.LinkTrackers,
      targetKey: 'id'
    });

    LinkTrackers.belongsTo(models.Tracker, {
      foreignKey: 'trackerId',
      through: models.LinkTrackers,
      targetKey: 'id'
    });
  };

  return LinkTrackers;
};

我已经尝试了许多小时来查找问题,但是失败了。最令人困惑的是,一个正在工作(Overlay),而另一个却没有工作(Tracker

1 个答案:

答案 0 :(得分:2)

在您的

link.js

Link.belongsToMany(models.Overlay, {
  as: 'overlays',
  through: models.LinkOverlays,
  foreignKey: 'linkId',
  targetKey: 'id',
});

Link.belongsToMany(models.Tracker, {
  as: 'trackers',
  through: models.LinkTrackers,
  foreignKey: 'trackerId', // should be linkId
  targetKey: 'id',
});

LinkOverlays的关系通过linkId,但与LinkTrackers的关系通过trackerId,它也应为linkId