Skip to main content
Yato uses MongoDB with Mongoose for data persistence. Models are defined in src/models/ and provide schema validation and database operations.

Database connection

The MongoDB connection is established in the ready event at src/index.js:11:
src/index.js
const mongoose = require('mongoose');

client.on('ready', async () => {
  await mongoose.connect(process.env.MONGO_URI, {
    useNewUrlParser: true,
    useUnifiedTopology: true
  })
    .then(() => console.log('✔ Connected to MongoDB'))
    .catch(err => console.log(`✖ Failed to connect to MongoDB\n${err}`));
});
The connection string is stored in the .env file as MONGO_URI.

Existing models

Yato currently has two database models:

User model

Stores user profiles with AniList integration:
src/models/user.js
const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true
  },
  id: {
    type: String,
    required: true
  },
  aniProfile: {
    type: mongoose.Schema.Types.Mixed,
    required: true
  }
});

module.exports = mongoose.model('user', userSchema, 'user');
Fields:
  • name - Discord username
  • id - Discord user ID
  • aniProfile - AniList profile data (flexible schema)

CSS model

Stores Counter-Strike server configurations:
src/models/css.js
const mongoose = require('mongoose');

const cssSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true
  },
  cmd: {
    type: String,
    required: true
  },
  ip: {
    type: String,
    required: true
  }
});

module.exports = mongoose.model('css', cssSchema, 'css');
Fields:
  • name - Server name or identifier
  • cmd - Command associated with this server
  • ip - Server IP address and port

Creating a new model

1

Create the model file

Create a new file in src/models/:
touch src/models/guild.js
2

Define the schema

src/models/guild.js
const mongoose = require('mongoose');

const guildSchema = new mongoose.Schema({
  guildId: {
    type: String,
    required: true,
    unique: true
  },
  prefix: {
    type: String,
    default: '!'
  },
  welcomeChannel: {
    type: String,
    default: null
  },
  logChannel: {
    type: String,
    default: null
  },
  muteRole: {
    type: String,
    default: null
  },
  modRoles: {
    type: [String],
    default: []
  }
}, {
  timestamps: true // Adds createdAt and updatedAt
});

module.exports = mongoose.model('guild', guildSchema, 'guilds');
3

Use the model in commands

src/commands/utilities/setprefix.js
const Guild = require('../../models/guild');

module.exports = {
  name: 'setprefix',
  description: 'Set server prefix',
  userRequiredPermissions: 'MANAGE_GUILD',
  expectedArgs: '<prefix:3:New prefix>',
  run: async ({ guild, respond }, arrayArgs, args) => {
    // Find or create guild document
    let guildDoc = await Guild.findOne({ guildId: guild.id });
    
    if (!guildDoc) {
      guildDoc = new Guild({ guildId: guild.id });
    }
    
    // Update prefix
    guildDoc.prefix = args.prefix;
    await guildDoc.save();
    
    respond(`Prefix updated to \`${args.prefix}\``);
  }
};

Schema types

Mongoose supports various schema types:
{
  stringField: String,
  numberField: Number,
  booleanField: Boolean,
  dateField: Date,
  bufferField: Buffer,
  objectIdField: mongoose.Schema.Types.ObjectId
}

Field options

Configure fields with validation and defaults:
OptionDescriptionExample
typeData typeString, Number, etc.
requiredMust have a valuerequired: true
uniqueMust be uniqueunique: true
defaultDefault valuedefault: 0
minMinimum value (numbers)min: 0
maxMaximum value (numbers)max: 100
minlengthMinimum length (strings)minlength: 3
maxlengthMaximum length (strings)maxlength: 32
enumAllowed valuesenum: ['option1', 'option2']
validateCustom validatorvalidate: (v) => v.length > 0

Common operations

Create a document

const User = require('./models/user');

const newUser = new User({
  name: 'John Doe',
  id: '123456789',
  aniProfile: { username: 'johndoe' }
});

await newUser.save();

Find documents

const user = await User.findOne({ id: '123456789' });

if (!user) {
  console.log('User not found');
}

Update documents

await User.updateOne(
  { id: '123456789' },
  { $set: { name: 'Jane Doe' } }
);

Delete documents

await User.deleteOne({ id: '123456789' });

Example: Complete model with methods

Add custom methods to your schemas:
src/models/guild.js
const mongoose = require('mongoose');

const guildSchema = new mongoose.Schema({
  guildId: {
    type: String,
    required: true,
    unique: true
  },
  prefix: {
    type: String,
    default: '!'
  },
  warnings: {
    type: Map,
    of: [{
      reason: String,
      moderator: String,
      timestamp: Date
    }],
    default: new Map()
  }
});

// Instance method
guildSchema.methods.addWarning = function(userId, reason, moderatorId) {
  const warnings = this.warnings.get(userId) || [];
  warnings.push({
    reason,
    moderator: moderatorId,
    timestamp: new Date()
  });
  this.warnings.set(userId, warnings);
  return this.save();
};

// Static method
guildSchema.statics.findByGuildId = function(guildId) {
  return this.findOne({ guildId });
};

module.exports = mongoose.model('guild', guildSchema, 'guilds');
Usage:
const Guild = require('./models/guild');

// Static method
const guild = await Guild.findByGuildId('123456789');

// Instance method
await guild.addWarning('userId', 'Spam', 'modId');

Mongoose version notes

Yato uses Mongoose v5.12.12, which is outdated. Some options like useNewUrlParser and useUnifiedTopology are deprecated in Mongoose 6+.
When upgrading Mongoose, update the connection:
// Old (v5)
await mongoose.connect(process.env.MONGO_URI, {
  useNewUrlParser: true,
  useUnifiedTopology: true
});

// New (v6+)
await mongoose.connect(process.env.MONGO_URI);

Best practices

const userSchema = new mongoose.Schema({
  id: {
    type: String,
    required: true,
    unique: true,
    index: true // Creates index
  }
});
const guildSchema = new mongoose.Schema({
  prefix: {
    type: String,
    required: true,
    minlength: 1,
    maxlength: 5,
    validate: {
      validator: (v) => !/\s/.test(v),
      message: 'Prefix cannot contain spaces'
    }
  }
});
const schema = new mongoose.Schema({
  // fields...
}, {
  timestamps: true // Adds createdAt and updatedAt
});
try {
  const user = await User.create(userData);
} catch (error) {
  if (error.code === 11000) {
    // Duplicate key error
    console.log('User already exists');
  } else {
    console.error('Database error:', error);
  }
}
Use MongoDB Compass or a similar tool to visualize and query your database during development.

Build docs developers (and LLMs) love