Sequelize (Sqlite) 无法识别 Discord 机器人中用户模型和集合模型之间的关联

问题描述 投票:0回答:1

创建新用户帐户时,我的不和谐机器人应该创建硬币余额和存储用户用硬币购买的角色的集合。所以逻辑是每个用户都有一个角色集合,他们自己的同一个 MasterCharacter 副本(我的皮卡丘是 10 级,你的是 2 级)。

我的所有控制台日志都显示这两个表是关联的,并且我在数据库浏览器中看到它们,但我不断收到此错误。

Error in execute: EagerLoadingError [SequelizeEagerLoadingError]: Collection is not associated to User!
    at Function._getIncludedAssociation (C:\Users\headm\code\wicked-after-death-bot\node_modules\sequelize\lib\model.js:565:13)
    at Function._validateIncludedElement (C:\Users\headm\code\wicked-after-death-bot\node_modules\sequelize\lib\model.js:502:53)
    at C:\Users\headm\code\wicked-after-death-bot\node_modules\sequelize\lib\model.js:421:37    
    at Array.map (<anonymous>)
    at Function._validateIncludedElements (C:\Users\headm\code\wicked-after-death-bot\node_modules\sequelize\lib\model.js:417:39)
    at Function.findAll (C:\Users\headm\code\wicked-after-death-bot\node_modules\sequelize\lib\model.js:1124:12)
    at async Function.findOne (C:\Users\headm\code\wicked-after-death-bot\node_modules\sequelize\lib\model.js:1240:12)
    at async Function.findOrCreate (C:\Users\headm\code\wicked-after-death-bot\node_modules\sequelize\lib\model.js:1411:21)
    at async Object.execute (C:\Users\headm\code\wicked-after-death-bot\commands\Account\CreateAccount.js:20:31)
    at async Object.execute (C:\Users\headm\code\wicked-after-death-bot\events\InteractionCreate.js:43:7)

这是我初始化表格的地方:

dbInit.js

const Sequelize = require('sequelize');
const sequelize = require('./Utils/sequelize');

const User = require('./Models/User.js')(sequelize, Sequelize.DataTypes);
const Shop = require('./Models/Shop.js')(sequelize, Sequelize.DataTypes);
const Collection = require('./Models/Collection.js')(sequelize, Sequelize.DataTypes);
const Enemy = require('./Models/Enemy.js')(sequelize, Sequelize.DataTypes);
const Character = require('./Models/Character.js')(sequelize, Sequelize.DataTypes);
const MasterCharacter = require('./Models/MasterCharacter.js')(sequelize, Sequelize.DataTypes);

// Model connections
User.hasOne(Collection, { foreignKey: 'user_id', as: 'collection' });
Collection.belongsTo(User, { foreignKey: 'user_id', as: 'user' });


Collection.hasMany(Character, { foreignKey: 'collection_id', as: 'characters' });
Character.belongsTo(Collection, { foreignKey: 'collection_id' });

Character.belongsTo(MasterCharacter, { foreignKey: 'master_character_id', as: 'masterCharacter' });
MasterCharacter.hasMany(Character, { foreignKey: 'master_character_id', as: 'instances' });

const shopData = require('./db/dbShop');
const characterData = require('./db/dbCharacters');
const enemyData = require('./db/dbEnemies');

// Authenticates connection to the database.
sequelize.authenticate()
  .then(() => {
    console.log('Connection has been established successfully.');
  })
  .catch(console.error);

// Sync changes and populate database
sequelize.sync({ force: true })
  .then(async () => {
    const shopPromises = shopData.map(item => Shop.upsert(item));
    const characterPromises = characterData.map(async item => {
      try {
        await Collection.findCreateFind({
          where: { collection_id: item.character_id },
          defaults: item,
          onDuplicate: ['collection_id'],
        });
      } catch (error) {
        console.error('Error syncing Collection:', error);
      }
    });
    const enemyPromises = enemyData.map(item => Enemy.upsert(item));
    console.log("User Associations:", Object.keys(User.associations));
console.log("Collection Associations:", Object.keys(Collection.associations));
    return Promise.all([...shopPromises, ...characterPromises, ...enemyPromises]);
  })
  .then(() => {
    console.log('All databases synced');
  })
  .catch((error) => {
    console.error('Error syncing databases:', error);
  });

async function fetchUserWithCollections(userId) {
  try {
    const user = await User.findOne({
      where: { user_id: userId },
      include: [{
        model: Collection,
        as: 'collections'
      }],
    });
    return user;
  } catch (error) {
    console.error(error);
    return null;
  }
}


module.exports = { User, Shop, Collection, Enemy, fetchUserWithCollections };

User.js 模型:


module.exports = (sequelize, DataTypes) => {
  const User = sequelize.define('User', {
    user_id: {
      type: DataTypes.STRING,
      allowNull: false,
      primaryKey: true,
    },
    balance: {
      type: DataTypes.INTEGER,
      allowNull: false,
    },
    createdAt: {
      type: DataTypes.DATE,
      defaultValue: DataTypes.NOW,
    },
    updatedAt: {
      type: DataTypes.DATE,
      allowNull: true,
    },
  });

  return User;
};

Collection.js 模型:

module.exports = (sequelize, DataTypes) => {
    const Collection = sequelize.define('Collection', {
      collection_id: {
        type: DataTypes.INTEGER,
        allowNull: false,
        primaryKey: true,
        autoIncrement: true,
      },
      user_id: {
        type: DataTypes.STRING,
        references: {
          model: 'Users',
          key: 'user_id'
        }
      },
      // ... any other attributes specific to the collection itself
    }, {
      timestamps: false,
    });
  
    return Collection;
  };
  

最后,这是 CreateAccount.js 的命令文件:

const { SlashCommandBuilder } = require('discord.js')
const { DataTypes, Sequelize } = require('sequelize')
const sequelize = require('../../Utils/sequelize')
const User = require('../../Models/User')(sequelize, DataTypes)
const Collection = require('../../Models/Collection')(sequelize, DataTypes)
const CharacterList = require('../../db/dbCharacters')

const specificCharacterIds = [0, 1, 2]

module.exports = {
  cooldown: 5,
  data: new SlashCommandBuilder()
    .setName('create')
    .setDescription('Create your economy account'),
  async execute(interaction) {
    const userId = interaction.user.id
    const t = await sequelize.transaction() // Initialize transaction

    try {
      const [user, created] = await User.findOrCreate({
        where: { user_id: userId },
        defaults: {
          balance: 730,
        },
        include: [{ model: Collection, as: 'collection' }], // Explicitly specify the foreignKey
        transaction: t,
      });

      // Function to calculate XP needed for next level
      const calculateXpNeeded = (level) => {
        if (level >= 1 && level <= 6) return 1000 * (level + 1)
        if (level >= 7 && level <= 8) return 6000 + (level + 1 - 6) * 2000
        if (level >= 9 && level <= 10) return 21000 + (level + 1 - 8) * 2000
        // more levels here
        return 1000 + (level - 1) * 1000
      }

      if (created) {
        await Promise.all(
          specificCharacterIds.map((id) => {
            const character = CharacterList.find((c) => c.character_id === id)
            return Collection.create(
              {
                collection_id: id,
                user_id: userId,
              },
              { transaction: t }
            )
          })
        )

        await t.commit() // Commit transaction

        return interaction.reply(
          `Your economy account has been created. You have 730 credits in your balance.`
        )
      } else {
        await t.rollback() // Rollback transaction
        return interaction.reply(
          `You already have an account. You currently have ${user.balance} coins in your account.`
        )
      }
    } catch (error) {
      await t.rollback() // Rollback transaction in case of error
      console.error('Error in execute:', error)
      return interaction.reply(
        'Something went wrong while creating your account.'
      )
    }
  },
}
javascript sqlite discord.js sequelize.js
1个回答
0
投票

您应该使用已经初始化的模型,而不是在

CreateAccount.js
中再次导入新模型:

const { User, Collection } = require('../../db/dbInit')
...
© www.soinside.com 2019 - 2024. All rights reserved.