【问题标题】:Set an alias for the junction table in a many to many relationship in sequelize在sequelize中为多对多关系中的联结表设置别名
【发布时间】:2021-08-31 21:35:34
【问题描述】:

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

基本上,我有三个(从技术上讲是四个,但第四个几乎与 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 的附加对象中。

退货示例:

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
    }
  },

这对于我使用数据的目的来说不太理想 - 基本上,还有一个 Guest 表与 Item 表具有等效的多对多关系,并且它的连接表称为 GuestItems。因此,当我搜索客人时 - 上述结果会吐出相同的数据,但使用的是 GuestItems 而不是 UserItems。

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

这可以通过 Sequelize 实现吗?我真的不想在返回中添加另一个重命名对象的步骤。

【问题讨论】:

    标签: javascript node.js postgresql sequelize.js


    【解决方案1】:

    要重命名 UserItems 表,您可以在“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: []});
        });
    

    这应该返回 Item 为:

    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 finders 来完成,您可能需要编写自己的原始 SQL 查询来将 'UserItems' 上的 'seen' 和 'owned' 列与 '项目”。

    【讨论】:

      猜你喜欢
      • 2021-11-05
      • 2019-04-29
      • 2020-05-15
      • 1970-01-01
      • 1970-01-01
      • 2014-04-15
      • 2013-03-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多