在 sequelize 的多对多关系中为联结 table 设置别名

Set an alias for the junction table in a many to many relationship in sequelize

如果标题令人困惑,我深表歉意,我不确定在这里使用什么术语。

基本上,我有三个(技术上有四个,但第四个几乎与 user.model.js 相同)模型:

user.model.js

'use strict';
const {Model} = require('sequelize');

module.exports = (sequelize, DataTypes) => {
    class User extends Model {
        static associate(models) {
            User.belongsToMany(models.Item, {
                through: 'UserItems',
                as: 'items',
                foreignKey: 'userId',
                otherKey: 'itemId'
            });
        }
    }

    User.init({
        name: {
            type: DataTypes.STRING,
            allowNull: false,
            unique: true
        },
        email: {
            type: DataTypes.STRING,
            allowNull: false,
            unique: true
        },
        password: {
            type: DataTypes.STRING,
            allowNull: false
        }
    }, {
        sequelize,
        modelName: 'User',
        paranoid: true,
        associations: true
    });
    return User;
};

item.model.js

'use strict';
const {
    Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
    class Item extends Model {
        /**
         * Helper method for defining associations.
         * This method is not a part of Sequelize lifecycle.
         * The `models/index` file will call this method automatically.
         */
        static associate(models) {
            Item.belongsToMany(models.Guest, {
                through: {
                    model: 'GuestItems',
                    unique: false
                },
                constraints: false,
                as: 'guests',
                foreignKey: 'itemId',
                otherKey: 'guestId'
            });
            Item.belongsToMany(models.User, {
                through: {
                    model: 'UserItems',
                    unique: false
                },
                constraints: false,
                as: 'users',
                foreignKey: 'itemId',
                otherKey: 'userId'
            });
        }
    }

    Item.init({
        dexId: {
            allowNull: true,
            type: DataTypes.INTEGER,
            defaultValue: null
        },
        name: {
            type: DataTypes.STRING,
            unique: true,
            allowNull: false
        },
        description: DataTypes.STRING,
        filename: DataTypes.STRING,
        firstSeen: {
            type: DataTypes.DATE,
            allowNull: true,
            defaultValue: null
        },
        firstAcquired: {
            type: DataTypes.DATE,
            allowNull: true,
            defaultValue: null
        },
    }, {
        sequelize,
        modelName: 'Item',
        paranoid: true
    });
    return Item;
};

useritems.model.js

'use strict';
const {
  Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
  class UserItems extends Model {
    /**
     * Helper method for defining associations.
     * This method is not a part of Sequelize lifecycle.
     * The `models/index` file will call this method automatically.
     */
    static associate(models) {
      // define association here
    }
  };
  UserItems.init({
    userId: DataTypes.INTEGER,
    itemId: DataTypes.INTEGER,
    seen: DataTypes.BOOLEAN,
    owned: DataTypes.BOOLEAN
  }, {
    sequelize,
    modelName: 'UserItems',
  });
  return UserItems;
};

在我的控制器中,我有

User.findByPk(id,
            {
                include: { model: db.Item, as: 'items', through: { attributes: ['seen']} },
                order: [[sequelize.literal('"items"."dexId"'), 'ASC']],
            })
            .then(data => {
                console.log(data.items);
                res.status(200).json({ items: data.items});
            })
            .catch(err => {
                console.log(err);
                res.status(204).json({ items: []});
            });

现在这工作得很好,除了 'seen' 和 'owned' 列被添加到一个名为 UserItems 的附加 object。

returned 项目的示例:

Item {
    dataValues: {
      id: 65,
      dexId: null,
      name: 'Fiona29',
      description: 'Quasi et sint.',
      filename: 'http://placeimg.com/640/480/animals',
      firstSeen: 2021-08-25T18:25:52.125Z,
      firstAcquired: 2021-08-26T02:36:05.250Z,
      createdAt: 2021-08-25T02:29:07.511Z,
      updatedAt: 2021-08-26T02:36:05.249Z,
      deletedAt: null,
      UserItems: [UserItems]
    },
    _previousDataValues: {
      id: 65,
      dexId: null,
      name: 'Fiona29',
      description: 'Quasi et sint.',
      filename: 'http://placeimg.com/640/480/animals',
      firstSeen: 2021-08-25T18:25:52.125Z,
      firstAcquired: 2021-08-26T02:36:05.250Z,
      createdAt: 2021-08-25T02:29:07.511Z,
      updatedAt: 2021-08-26T02:36:05.249Z,
      deletedAt: null,
      UserItems: [UserItems]
    },
    _changed: Set(0) {},
    _options: {
      isNewRecord: false,
      _schema: null,
      _schemaDelimiter: '',
      include: [Array],
      includeNames: [Array],
      includeMap: [Object],
      includeValidated: true,
      raw: true,
      attributes: undefined
    },
    isNewRecord: false,
    UserItems: UserItems {
      dataValues: [Object],
      _previousDataValues: [Object],
      _changed: Set(0) {},
      _options: [Object],
      isNewRecord: false
    }
  },

这不太适合我使用数据的目的 - 基本上,还有一个访客 table 与项目 table 具有等效的 many-to-many 关系,并且它的连接 table 称为 GuestItems。因此,当我搜索客人时 - 上面的结果吐出相同的数据,但使用 GuestItems 而不是 UserItems。

希望 发生的是 UserItems/GuestItems 重命名为 Items。或者理想情况下,只需将 UserItems/GuestItems table 中的 'seen' 和 'owned' 列添加到其余结果中,而不是它自己的 'UserItems/GuestItems' 属性。

这可以用 Sequelize 完成吗?我真的不想在 return.

中添加另一个重命名 object 的步骤

要仅重命名 UserItems table,您可以在“through”选项中使用“as”选项:

User.findByPk(id, 
    {
        include: { model: db.Item, as: 'items', through: { as: "Items", attributes: ['seen', 'owned']} },
        order: [[sequelize.literal('"items"."dexId"'), 'ASC']],
    })
    .then(data => {
        console.log(data.items);
        res.status(200).json({ items: data.items});
    })
    .catch(err => {
        console.log(err);
        res.status(204).json({ items: []});
    });

这应该return项为:

Item {
    dataValues: {
      id: 65,
      dexId: null,
      name: 'Fiona29',
      description: 'Quasi et sint.',
      filename: 'http://placeimg.com/640/480/animals',
      firstSeen: 2021-08-25T18:25:52.125Z,
      firstAcquired: 2021-08-26T02:36:05.250Z,
      createdAt: 2021-08-25T02:29:07.511Z,
      updatedAt: 2021-08-26T02:36:05.249Z,
      deletedAt: null,
      Items: {
        seen: false,
        owned: false
      }
    }

至于将它们直接保存在 'Item' 中不确定是否可以使用 sequelize 查找器来完成,您可能需要编写自己的原始 SQL 查询以加入 'seen' 和'UserItems' 上的 'owned' 列 'Item'。