SQL 排行榜问题 nodejs discord.js

Posted

技术标签:

【中文标题】SQL 排行榜问题 nodejs discord.js【英文标题】:SQL Leaderboard issue nodejs discord.js 【发布时间】:2019-07-26 08:48:26 【问题描述】:

我创建了一个简单的不和谐机器人,其中包含消息侦听器等,它在某些事件上将数据添加到 mysql 数据库中。

我的代码为在频道中添加 +1 点评分(完全有效):

//If message is sent add points to scores table

    con.query(`SELECT * FROM scores WHERE user="$message.author.id" AND guild= "$message.guild.id"`, (err, rows) => 
        if (err) throw err;

        let sql;
        if (rows.length < 1) 
            sql = `INSERT INTO scores (user, guild, points) VALUES ('$message.author.id', '$message.guild.id', '1')`, (err, rows) => 
                if (err) throw err;
            ;

         else 
            let score = rows[0].scores;
            sql = `UPDATE scores SET points = points +1 WHERE user="$message.author.id" AND guild= "$message.guild.id"`;
        ;

        con.query(sql);

    );

一旦排行榜命令进入频道;我想获取分数表中的数据,将其分类到前 10 名并以不和谐的方式打印(通过使用 message.channel.send 或 message.channel.send(embed)。

以下代码是我目前所拥有的:

const Discord = require("discord.js");

module.exports.run = async (bot, message, args, con) => 
    
const top10 = `SELECT user, points, lstmsg FROM scores WHERE guild = '$message.guild.id' ORDER BY cast(points as SIGNED) ASC LIMIT 10`;
//user, points, lstmsg from scores WHERE guild= '$message.guild.id' ORDER BY points DESC LIMIT 10`;

con.query(top10, function(err, rows, fields) 
  if (err) throw err;

  //    const embed = new Discord.RichEmbed()
  //   .setTitle("Leaderboard")
  //   .setAuthor(bot.user.username,)
  //   .setDescription("Inactive..... Boooooo!")
  //   .addField(rows[1])
  //   .setColor(0x00AE86)


return message.channel.send(rows);

);



module.exports.help = 
    name: "top10",
    usage: "``prefix`` top10",
    description: "top 10 points",

但它发送的内容不一致:

[object Object]
[object Object]
[object Object]
[object Object]
[object Object]
[object Object]
[object Object]
[object Object]
[object Object]
[object Object]

有什么想法吗?提前致谢

使用 JSON.Stringify 会返回如下结果:

["user":"123456789876587659","points":"2","lstmsg":"2019-03-04T22:40:40.000Z","user":"378976806730203147","points":"80","lstmsg":"2019-03-05T10:10:18.000Z","user":"123456789101112131","points":"93","lstmsg":"2019-03-04T22:40:29.000Z","user":"378976806730203147","points":"168","lstmsg":"2019-03-05T10:10:18.000Z","user":"456567676767867677","points":"289","lstmsg":"2019-03-04T22:41:01.000Z"]

我希望数据显示为:

User:
Points:
Last Message: 

对于数据库中的每个条目(限制为 10 个)。

我还尝试了以下资源:SQLite-Based Points system

代码:

const Discord = require("discord.js");

module.exports.run = async (bot, message, args, con) => 
  
    var top10query = "SELECT * FROM scores WHERE guild = ? ORDER BY points DESC LIMIT 10"
    const top10 = con.query(top10query)

    // Now shake it and show it! (as a nice embed, too!)
    const embed = new Discord.RichEmbed()
      .setTitle("Leaderboard")
      .setAuthor(bot.user.username, bot.user.avatarURL)
      .setDescription("Our top 10 points leaders!")
      .setColor(0x00AE86);

    for (const data of top10) 
      embed.addField(bot.users.get(data.user).tag, `$data.points points (last message $data.lstmsg)`);
    
    return message.channel.send( embed );
  






module.exports.help = 
  name: "inactive",
  usage: "``prefix`` inactive",
  description: "Bottom 30 inactive & last message date for current weeks",

但我得到一个错误(很可能是因为该示例适用于 SQLlite 并适用于 MySQL):

(node:2880) UnhandledPromiseRejectionWarning: TypeError: top10 is not iterable

【问题讨论】:

【参考方案1】:

如果还没有的话,我建议userguild 是分数表的复合主键(或唯一键)。这可以在 SQL 中完成:

ALTER TABLE scores DROP PRIMARY KEY, ADD PRIMARY KEY (user, guide)

对于您的 SQL 语句,INSERT ON DUPLICATE KEY UPDATE 是一个常见的查询。它依赖于上面的唯一键或主键。

INSERT INTO scores (user, guild, points) VALUES ('$message.author.id', '$message.guild.id', '1')
ON DUPLICATE KEY UPDATE points=points+1

另见Preventing SQL injection in Node.js

【讨论】:

承认这不是你问的问题,但是代码有点乱,而且两部分都有需要修复的 SQL 注入(无需信任不和谐机器人)。 感谢您的建议!它只是一个用于跟踪行会中非活动用户的基本机器人,所以并不真正关心这个特定项目的 SQL 注入。我可能会稍后更新它以防止这种情况发生,但不是现在。【参考方案2】:

尝试使用JSON.stringify();,文档为here。

var o = 
  a: 2, 
  b: 3

console.log(JSON.stringify(o));  //""a":2,"b":3"

【讨论】:

JSON.stringify 正是我所需要的!!谢谢!在正确的轨道上.. 我将如何拆分结果以显示:用户:积分:最后一条消息:每个条目?结果显示为:["user":"123456789876587659","points":"2","lstmsg":"2019-03-04T22:40:40.000Z","user":"378976806730203147" ,"points":"77","lstmsg":"2019-03-04T23:47:47.000Z","user":"123456789101112131","points":"93","lstmsg":"2019 -03-04T22:40:29.000Z","user":"456567676767867677","points":"289","lstmsg":"2019-03-04T22:41:01.000Z"] 因为这个答案对你有用,我建议你点击旁边的小空心复选标记将其标记为正确,这样如果人们有和你一样的问题。如果您使用rows[x].key,那么它将为您提供该值,例如console.log(rows[0].points); //2 将返回2,另一个示例是rows[1].points,这将返回77,依此类推。【参考方案3】:

我用map来绘制结果。

const Discord = require("discord.js");

module.exports.run = async (bot, message, args, con) => 

  const top10query = `SELECT user, points, lstmsg FROM scores WHERE guild = '$message.guild.id' ORDER BY cast(points as SIGNED) DESC LIMIT 10`

  const query = querytxt => 
    return new Promise((resolve, reject) => 
      con.query(querytxt, (err, results, fields) => 
        if (err) reject(err);
        resolve([results, fields]);
      );
    );
  ;
  const [results, fields] = await query(top10query);

  const map1 = results.map(results => ` ** User:** $bot.users.get(results.user).username \n **Messages:** $results.points \n **Last message:** $results.lstmsg \n`);
  message.channel.send(map1)

module.exports.help = 
  name: "top10",
  usage: "``prefix`` top10",
  description: "top 10 points",

【讨论】:

以上是关于SQL 排行榜问题 nodejs discord.js的主要内容,如果未能解决你的问题,请参考以下文章

discord.js - 排行榜/顶部命令显示错误的顺序

discord.js - 排行榜未定义的用户名

不和谐机器人 |使用 discord.js 和 MongoDB 进行排名(排行榜?)系统

如何在 discord.js 中使用 JSON 数据库制作排行榜

排行榜命令中未定义的用户名 [ quick.db / discord.js ]

Javascript discord.js 排行榜