简体   繁体   English

在 Sequelize 中查询关联表

[英]Querying association tables in Sequelize

I have two tables ( users and games ) joined by an association table ( game_players ), creating a many-to-many relationship:我有两个表( usersgames )由关联表( game_players )连接,创建多对多关系:

models.Game.belongsToMany(models.User, { through: models.GamePlayer, as: 'players' });
models.User.belongsToMany(models.Game, { through: models.GamePlayer, foreignKey: 'user_id' });

In addition to the foreign keys user_id and game_id , game_players has a few extra columns for link-specific data:除了外键user_idgame_idgame_players还有一些额外的列用于链接特定的数据:

sequelize.define('game_player', {
    isReady: {
        defaultValue: false,
        type: Sequelize.BOOLEAN,
        field: 'is_ready'
    },
    isDisabled: {
        defaultValue: false,
        type: Sequelize.BOOLEAN,
        field: 'is_disabled'
    },
    powerPreferences: {
        type: Sequelize.TEXT,
        field: 'power_preferences'
    },
    power: {
        type: Sequelize.STRING(2),
        defaultValue: '?'
    }
}, {
    underscored: true
});

Suppose I want to fetch a game and eagerly load active players.假设我想获取一个游戏并急切地加载活跃玩家。 This was my first effort:这是我的第一次尝试:

db.models.Game.findAll({
    include: [{
        model: db.models.User,
        as: 'players',
        where: { 'game_player.isDisabled': false }
    }]
}).nodeify(cb);

This generates the following SQL, which throws the error Column players.game_player.isDisabled does not exist :这会生成以下 SQL,它会抛出错误Column players.game_player.isDisabled does not exist

SELECT "game"."id", 
   "game"."name", 
   "game"."description", 
   "game"."variant", 
   "game"."status", 
   "game"."move_clock"                       AS "moveClock", 
   "game"."retreat_clock"                    AS "retreatClock", 
   "game"."adjust_clock"                     AS "adjustClock", 
   "game"."max_players"                      AS "maxPlayers", 
   "game"."created_at", 
   "game"."updated_at", 
   "game"."gm_id", 
   "game"."current_phase_id", 
   "players"."id"                            AS "players.id", 
   "players"."email"                         AS "players.email", 
   "players"."temp_email"                    AS "players.tempEmail", 
   "players"."password"                      AS "players.password", 
   "players"."password_salt"                 AS "players.passwordSalt", 
   "players"."action_count"                  AS "players.actionCount", 
   "players"."failed_action_count"           AS "players.failedActionCount", 
   "players"."created_at"                    AS "players.created_at", 
   "players"."updated_at"                    AS "players.updated_at", 
   "players.game_player"."is_ready"          AS 
   "players.game_player.isReady", 
   "players.game_player"."is_disabled"       AS 
   "players.game_player.isDisabled", 
   "players.game_player"."power_preferences" AS 
   "players.game_player.powerPreferences", 
   "players.game_player"."power"             AS "players.game_player.power", 
   "players.game_player"."created_at"        AS 
   "players.game_player.created_at", 
   "players.game_player"."updated_at"        AS 
   "players.game_player.updated_at", 
   "players.game_player"."game_id"           AS 
   "players.game_player.game_id", 
   "players.game_player"."user_id"           AS 
   "players.game_player.user_id" 
FROM   "games" AS "game" 
   INNER JOIN ("game_players" AS "players.game_player" 
               INNER JOIN "users" AS "players" 
                       ON "players"."id" = "players.game_player"."user_id") 
           ON "game"."id" = "players.game_player"."game_id" 
              AND "players"."game_player.isdisabled" = false;

Clearly Sequelize is wrapping my constraint alias with incorrect quotes: 'players'.'game_player.isdisabled' should be 'players.game_player'.isdisabled.显然,Sequelize 用不正确的引号包装了我的约束别名:'players'.'game_player.isdisabled' 应该是 'players.game_player'.isdisabled。 How can I revise my Sequelize code above to correctly query this column?如何修改上面的 Sequelize 代码以正确查询此列?

I got it, but only through manually browsing the repository's closed tickets and coming upon #4880 .我明白了,但只能通过手动浏览存储库的已关闭票证并找到#4880

Clauses using joined table columns that don't work out of the box can be wrapped in $ .使用开箱即用的连接表列的子句可以用$包装。 I honestly don't understand its magic, because I swear I don't see any documentation for it.老实说,我不明白它的魔力,因为我发誓我没有看到任何有关它的文档。 Modifying my query above achieved what I wanted:修改我上面的查询实现了我想要的:

db.models.Game.findAll({
    include: [{
        model: db.models.User,
        as: 'players',
        where: { '$players.game_player.is_disabled$': false }
    }]
}).nodeify(cb);

After searching around, I found that through.where can also be used:找了through.where ,发现through.where也可以用:

db.models.Game.findAll({
    include: [{
        model: db.models.User,
        as: 'players',
        through: {  where: { isDisabled: false } }
    }]
})

Reference:参考:
Is it possible to filter a query by the attributes in the association table with sequelize?是否可以使用 sequelize 通过关联表中的属性过滤查询?
Eager loading with Many-to-Many relationships 多对多关系的热切加载

Your query should be on the join table with the 'where' condition, and then you should use the 'include' clause to include the two other models, like this:您的查询应该在带有 'where' 条件的连接表上,然后您应该使用 'include' 子句来包含另外两个模型,如下所示:

    db.models.GamePlayer.findAll({
        where: {isDisabled: false},
        attributes: [],
        include: [models.User, models.Game]
    }).then(function(result){
        ....
    });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM