javascriptdatabasemongodbdiscorddiscord.js

db.Collection Is Not a Constructor


I'm having this issue where I'm trying to create a leveling system in Discord using discord.js and MongoDB. Every time I try to upload my data to the database, I keep getting the error message

level is not a constructor

I've followed the instructions from Why save() in mongoose is not a function? post on saving new data to MongoDB, but I'm still getting the same error.

Here is my code that I've been working on:

const { Events, Message } = require("discord.js");
const Level = require("../models/Level");
const getLevelXP = require("../utility/getLevelXP");

function getRandomXP(min, max) {
  min = Math.ceil(min);
  max = Math.floor(max);

  return Math.floor(Math.random() * (max - min + 1)) + min;
}

module.exports = {
  name: Events.MessageCreate,
  async execute(message) {
    if (!message.inGuild() || message.author.bot) return;

    const XPToGive = getRandomXP(5, 15);

    const query = {
      userId: message.author.id,
      guildId: message.guild.id,
    };

    try {
      await Level.findOne(query).then(async (level) => {
        if (!level) {
          const newLevel = new level({
            userId: message.author.id,
            guildId: message.guild.id,
            xp: XPToGive,
          });

          await newLevel.save();
          return;
        }

        level.xp += XPToGive;

        if (level.xp > getLevelXP(level.level)) {
          level.xp = 0;
          level.level += 1;

          message.channel.send(
            `@${message.member} have been leveled up to **Level ${level.level}**`,
          );
        }

        await level.save().catch((error) => {
          console.error(`[ERROR] ${error}`);
          return;
        });
      });
    } catch (error) {
      console.error(`[ERROR] ${error}`);
    }
  },
};

I'm having trouble with using find() instead of findOne() in my code. It's giving me more errors, and I really want my code to be error-free and able to save my data in the database.


Solution

  • Hey there I know this answer comes a bit late but I might still be able to help you out! We look especially at the following snippets of your code:

    const Level = require("../models/Level");
    

    and

    await Level.findOne(query).then(async (level) => {
            if (!level) {
              const newLevel = new level({
                userId: message.author.id,
                guildId: message.guild.id,
                xp: XPToGive,
              });
    
              await newLevel.save();
              return;
            }
     }
    
    

    You are importing the Level model and assign it to Level in the first snippet. In the second snippet you look for a specific document based on your query. If none is found you are trying to create the missing document. However - and here comes the issue - you are not calling the imported class Level but rather the document level that is null because none was found. So changing new level({ to new Level({ will resolve your issue.

    On top of this issue you should not use await and .then() at the same time. That's a very uncommon behaviour. Here's an article about the difference of await and .then() and their benefits: https://dev.to/masteringjs/using-then-vs-async-await-in-javascript-2pma.