You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Mongoose代码转为MySQL代码并实现API数据入库(React+Node)

解决方案:Mongoose转MySQL+API数据自动入库+前后端整合

一、先创建MySQL表结构

首先在MySQL数据库中创建匹配业务需求的数据表:

CREATE TABLE IF NOT EXISTS stats (
    id INT PRIMARY KEY, -- 玩家ID作为唯一主键,避免重复数据
    position INT NOT NULL,
    name VARCHAR(255) NOT NULL,
    alliance VARCHAR(255),
    score INT NOT NULL,
    status VARCHAR(50),
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

二、Mongoose代码转MySQL版本(自动拉取API数据入库)

使用mysql2/promise库(支持async/await,比回调更易维护),替换原Mongoose逻辑:

import fetch from 'node-fetch';
import mysql from 'mysql2/promise';

// MySQL数据库连接配置
const dbConfig = {
  host: 'localhost',
  user: '你的MySQL用户名',
  password: '你的MySQL密码',
  database: 'highscore' // 对应你创建的数据库名
};

async function fetchAndSavePlayers() {
  try {
    // 1. 建立MySQL连接
    const connection = await mysql.createConnection(dbConfig);
    
    // 2. 拉取两个API的数据
    const rankRes = await fetch("http://localhost:3008/api/highscore/players");
    const rankData = await rankRes.json();
    const playerRes = await fetch("http://localhost:3008/api/players");
    const playerData = await playerRes.json();

    // 3. 合并玩家基础信息与排名数据
    const mergedPlayers = playerData.players.map(player => {
      const rankInfo = rankData.players.find(r => r.id === player.id);
      return {
        id: player.id,
        name: player.name,
        status: player.status,
        alliance: player.alliance,
        position: rankInfo?.position || 0,
        score: rankInfo?.score || 0
      };
    });

    // 4. 批量插入/更新数据(存在则更新,避免重复)
    const insertQuery = `
      INSERT INTO stats (id, position, name, alliance, score, status)
      VALUES ?
      ON DUPLICATE KEY UPDATE
        position = VALUES(position),
        score = VALUES(score),
        alliance = VALUES(alliance),
        status = VALUES(status),
        updated_at = CURRENT_TIMESTAMP
    `;
    // 转换为MySQL批量插入所需的二维数组格式
    const values = mergedPlayers.map(p => [p.id, p.position, p.name, p.alliance, p.score, p.status]);
    await connection.query(insertQuery, [values]);

    console.log('数据同步完成');
    await connection.end();
  } catch (err) {
    console.error('同步失败:', err);
  }
}

// 立即执行一次测试
fetchAndSavePlayers();

三、后端接口整合与定时任务

1. 完善Express后端(含定时任务)

把自动同步逻辑和前端查询接口整合,同时添加每日定时任务:

const express = require('express');
const mysql = require('mysql2/promise');
const schedule = require('node-schedule');
const app = express();
app.use(express.json());

const dbConfig = { /* 同上面的数据库配置 */ };

// 前端获取玩家数据的接口
app.get('/api/players', async (req, res) => {
  try {
    const connection = await mysql.createConnection(dbConfig);
    const [rows] = await connection.query('SELECT * FROM stats ORDER BY position ASC');
    await connection.end();
    res.json({ players: rows });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

// 手动触发同步的接口(可选)
app.post('/api/sync-players', async (req, res) => {
  try {
    await fetchAndSavePlayers();
    res.send('同步成功');
  } catch (err) {
    res.status(500).send('同步失败');
  }
});

// 每日凌晨2点自动同步数据
schedule.scheduleJob('0 0 2 * * *', () => {
  console.log('开始每日数据同步...');
  fetchAndSavePlayers();
});

app.listen(3000, () => console.log('后端服务运行在3000端口'));

需先安装依赖:npm install express mysql2 node-schedule node-fetch

2. 替换原有手动插入接口

原/create接口可被上述批量同步逻辑替代,若需保留手动插入功能,可调整为单条数据的插入/更新:

app.post('/create', async (req, res) => {
  const { position, name, alliance, points, id, status } = req.body;
  try {
    const connection = await mysql.createConnection(dbConfig);
    await connection.query(
      `INSERT INTO stats (id, position, name, alliance, score, status)
       VALUES (?, ?, ?, ?, ?, ?)
       ON DUPLICATE KEY UPDATE
         position = VALUES(position),
         score = VALUES(score),
         alliance = VALUES(alliance),
         status = VALUES(status)`,
      [id, position, name, alliance, points, status]
    );
    await connection.end();
    res.send('数据已保存');
  } catch (err) {
    console.log(err);
    res.status(500).send('保存失败');
  }
});

四、前端代码优化

调整为调用自己后端的接口,简化前端逻辑:

import { useState, useEffect } from 'react';
import axios from 'axios';

const Table = () => {
  const [players, setPlayers] = useState([]);
  const [perPage, setPerPage] = useState(10);
  const [currentPage, setCurrentPage] = useState(1);

  const fetchData = async () => {
    try {
      const res = await axios.get('http://localhost:3000/api/players');
      setPlayers(res.data.players);
    } catch (err) {
      console.error('获取数据失败:', err);
    }
  };

  useEffect(() => {
    fetchData();
    // 可选:每5分钟自动刷新前端数据
    const interval = setInterval(fetchData, 5 * 60 * 1000);
    return () => clearInterval(interval);
  }, []);

  // 分页逻辑
  const startIndex = (currentPage - 1) * perPage;
  const currentPlayers = players.slice(startIndex, startIndex + perPage);

  return (
    <div>
      {/* 你的表格渲染代码,使用currentPlayers即可 */}
    </div>
  );
};

export default Table;

内容的提问来源于stack exchange,提问作者yandry santana

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 13:55:20