React Native健身数据提交MongoDB的格式适配问题求助
健身数据收集应用的Schema与数据格式适配问题
问题背景
我正在开发一款React Native应用,用于收集用户输入的可变健身数据并提交至MongoDB数据库。收集的信息包含动作名称以及由重量和次数组成的数组,现在纠结是修改Mongoose Schema适配现有前端数据格式,还是修改前端代码将数据处理为匹配Schema的格式。
当前Mongoose Schema
const exerciseSchema = new mongoose.Schema([{ exerciseName: String, sets: [{ weight: Number, reps: Number }] }]);
前端收集的数据格式
[ {"Seated Leg Extensions": [{"weight":"12","reps":"22"}, {"weight":"12","reps":"2"}]}, {"Shrugs": [{"weight":"12","reps":"33"}] } ]
前端核心代码
import React, { useState } from 'react'; import axios from 'axios'; import { View, ScrollView, Modal, Picker, Text, TouchableOpacity, TextInput, StyleSheet, Button, FlatList } from 'react-native'; import myExerciseList from './ExerciseList'; import {ExerciseView} from './Sets'; const exercises = myExerciseList const ExerciseList = () => { const [dataFromChild, setDataFromChild] = useState([]); const handleChildData = (data) => { setDataFromChild([...dataFromChild, data]); console.log(dataFromChild) }; const [views, setViews] = useState([]); const [visible, setVisible] = useState(false); const [selectedValue, setSelectedValue] = useState(null); //Form data to be sent to the database const [formData, setFormData] = useState( [{ exerciseName: '', sets: [{ weight: '', reps: '' }] }] ) const handlePress = (item) => { setSelectedValue(item) const newView = <View key={views.length} > <Text>Exercise: {item.name}</Text> <ExerciseView exerciseName={item.name} onData={handleChildData} ></ExerciseView> </View>; setViews([...views, newView]); setVisible(false); }; const submitAll = async (event) => { event.preventDefault() const dataSend = JSON.stringify(dataFromChild) console.log(dataSend) const updatedFormData = dataFromChild.map((exercise) => { const exerciseName = Object.keys(exercise)[0] const sets = exercise[exerciseName].map((set) => { return { weight: set.weight, reps: set.reps } }) return { exerciseName, sets } }) setFormData({ exercises: updatedFormData }) console.log(formData) try { const response = await axios.post('http://localhost:3000/api/v1/myworkouts', formData); console.log(response.data); } catch (error) { console.error(error); } console.log(dataSend) } return () export default ExerciseList;
后端Express路由代码
const express = require('express'); const router = express.Router(); const Exercise = require('../models/workouts'); // Create a new exercise router.post('/', async (req, res) => { const exercise = new Exercise({ exerciseName: req.body.exerciseName, sets: req.body.sets, weight: req.body.weight, reps: req.body.reps, }); try { const newExercise = await exercise.save(); res.status(201).json(newExercise); } catch (err) { res.status(400).json({ message: err.message }); } }); module.exports = router;
解决方案建议
优先修改前端数据处理逻辑,适配现有Schema
现有Mongoose Schema的设计更合理,明确的结构便于后续查询、统计(比如按动作名称筛选、计算总重量等)。前端当前的键值对格式会增加数据库操作的复杂度,不建议为它修改Schema。
具体修改点:
- 修正数据类型转换:前端收集的重量和次数是字符串,需转为数字匹配Schema的
Number类型:const sets = exercise[exerciseName].map((set) => { return { weight: Number(set.weight), reps: Number(set.reps) } }) - 避免异步状态更新的坑:
setFormData是异步操作,直接用formData发请求会拿到旧值,应直接使用转换后的updatedFormData:// 移除setFormData相关代码,直接使用updatedFormData try { // 若后端支持单条创建,循环提交多个动作 const responses = await Promise.all(updatedFormData.map(exercise => axios.post('http://localhost:3000/api/v1/myworkouts', exercise) )); console.log('所有数据提交成功', responses); } catch (error) { console.error(error); } - 修复后端路由冗余字段:后端代码里错误添加了
weight和reps,这些已包含在sets数组中,需移除:
若想批量提交多个动作,可新增后端批量路由:router.post('/', async (req, res) => { const exercise = new Exercise({ exerciseName: req.body.exerciseName, sets: req.body.sets }); try { const newExercise = await exercise.save(); res.status(201).json(newExercise); } catch (err) { res.status(400).json({ message: err.message }); } });
前端对应发送router.post('/batch', async (req, res) => { try { const exercises = await Exercise.insertMany(req.body.exercises); res.status(201).json(exercises); } catch (err) { res.status(400).json({ message: err.message }); } });{ exercises: updatedFormData }即可。
不推荐修改Schema适配前端格式
如果修改Schema适配前端的动态键格式,会导致:
- 数据库查询困难,无法直接按
exerciseName筛选、排序 - 数据结构不规范,后续扩展(如添加动作类型、备注)会非常麻烦
内容的提问来源于stack exchange,提问作者Diego Guardiola
相关产品推荐
相关产品推荐

