如何通过user_id获取MongoDB中invites表的invite_link值(discord.js v14)
问题:通过user_id从MongoDB的invites表获取invite_link是否可行?
我正在用discord.js v14开发Discord机器人,希望仅通过user_id从MongoDB的invites表中获取对应的invite_link值,请问这是否可行?
以下是我当前的实现代码:
const { SlashCommandBuilder } = require("@discordjs/builders") const Discord = require("discord.js") const { QuickDB } = require("quick.db"); const db2 = new QuickDB(); const mongodb = require("mongodb"); const username = encodeURIComponent('censored'); const password = encodeURIComponent("censored") const dbname = 'censored'; const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args)); const clusterUrl = "censored"; const authMechanism = "DEFAULT"; const url = `mongodb://${username}:${password}@${clusterUrl}/${username}`; const client = new mongodb.MongoClient(url); const db = client.db(dbname) client.connect().then(() => { console.log("Data: Connected") }).catch(err => console.error(err)) module.exports = { data: new SlashCommandBuilder() .setName("invite") .setDescription("Create invite to download server"), execute: async function(interaction, guilds, client, invites) { if(interaction instanceof Discord.CommandInteraction) { const guild = interaction.client.guilds.cache.get(`1013773663910232184`) if(await db.collection('blacklist').findOne({ user_id: `${interaction.member.id}` })){ return interaction.reply({ content: `You cant acces to this command! (Error code: 502)`, ephemeral: true}) } const query = { user_id: `${interaction.member.id}` }; const options = { projection: { invite_link: 1 } //only return invite link }; const inviteLink2 = await db.collection('invites').findOne(query, options); if(await db.collection('invites').findOne({ user_id: `${interaction.member.id}` })) { return interaction.reply({ content: `You always have invite code! This is your invite code: ${inviteLink2}`}) } const invitecode = await guild.invites.create('1013793499189100574', { maxAge: 18000, maxUses: 1} ); db.collection('invites').insertOne({ user_id: `${interaction.member.id}`, invite_link: `${invitecode.url}` }) interaction.reply({ content: `This is your invite: ${invitecode.url} , DO NOT SEND THIS LINK TO ANYONE. Invite expires in 3 minutes.`, ephemeral: true}) console.log(`${invitecodegetindatabase}`) } } }
解答
完全可行,通过MongoDB的findOne方法结合查询条件和投影参数,就能仅获取目标字段。不过你的代码存在几个问题,需要优化:
重复数据库查询:你先执行了一次
findOne获取inviteLink2,之后又重复执行一次判断用户是否存在。可以直接用第一次查询的结果判断,减少数据库操作:const inviteLinkDoc = await db.collection('invites').findOne({ user_id: interaction.member.id }, { projection: { invite_link: 1, _id: 0 } }); if (inviteLinkDoc) { // 用户已有邀请链接 }回复内容错误:直接输出
inviteLink2会返回整个文档对象(显示[object Object]),需要提取invite_link字段:return interaction.reply({ content: `你已经有邀请链接了!链接是:${inviteLinkDoc.invite_link}`, ephemeral: true })未定义变量报错:代码末尾的
invitecodegetindatabase未定义,会导致控制台报错,建议移除该语句。连接逻辑优化:当前MongoDB连接逻辑放在全局,虽然能工作,但建议将连接封装成单独函数,确保连接成功后再执行命令,避免因连接未就绪导致的错误。
优化后的核心代码片段:
execute: async function(interaction, guilds, client, invites) { if(interaction instanceof Discord.CommandInteraction) { const guild = interaction.client.guilds.cache.get('1013773663910232184'); // 黑名单判断 const isBlacklisted = await db.collection('blacklist').findOne({ user_id: interaction.member.id }); if (isBlacklisted) { return interaction.reply({ content: '你无法使用此命令!(错误代码: 502)', ephemeral: true }); } // 查询用户已有邀请链接 const inviteLinkDoc = await db.collection('invites').findOne( { user_id: interaction.member.id }, { projection: { invite_link: 1, _id: 0 } } // 只返回invite_link,排除默认的_id字段 ); if (inviteLinkDoc) { return interaction.reply({ content: `你已经有邀请链接了!链接是:${inviteLinkDoc.invite_link}`, ephemeral: true }); } // 创建新邀请并保存到数据库 const invitecode = await guild.invites.create('1013793499189100574', { maxAge: 18000, maxUses: 1 }); await db.collection('invites').insertOne({ user_id: interaction.member.id, invite_link: invitecode.url }); interaction.reply({ content: `这是你的邀请链接:${invitecode.url},请勿转发给他人。邀请链接将在3分钟后过期。`, ephemeral: true }); } }
内容的提问来源于stack exchange,提问作者Smkv 2022
相关产品推荐
相关产品推荐

