MERN栈CRUD应用搜索功能报BSONTypeError错误求解决
问题原因
你遇到的BSONTypeError是因为Express路由匹配顺序引发的冲突:
- 服务端先定义了
app.get('/user/:id')路由,该路由会匹配所有/user/xxx格式的请求,包括你搜索用户时发送的/user/用户名请求。 - 当搜索请求进入时,Express会把用户名当作
id参数传入该路由,随后执行ObjectId(updateId)——但用户名并非合法的MongoDB ObjectId(要求是12字节字符串、24位十六进制字符串或整数),因此抛出错误。 - 你定义的
app.get('/user/:name')路由永远不会被触发,因为前面的/:id路由已经优先匹配了所有请求。
解决方案
推荐使用查询参数实现搜索功能,彻底避免路由冲突,同时让接口设计更规范:
1. 修改客户端代码(Search.js)
将请求URL改为带查询参数的格式:
import React from 'react'; const Search = () => { const searchHandle = e => { e.preventDefault(); const userName = e.target.search.value; // 修改为查询参数格式的请求URL fetch(`http://localhost:5000/user/search?name=${userName}`) .then(res => res.json()) .then(data => console.log(data)) .catch(err => console.log(err)); console.log(typeof(userName)); } return ( <div className='px-3 py-2 w-3/4'> <h1 className='text-3xl font-bold mb-3'>Search User:</h1> <form onSubmit={searchHandle}> <input className='bg-gray-200 rounded p-2 w-3/4' type="search" name="search" id="name" /> <button className='bg-blue-500 mx-2 py-2 px-4 rounded' type='submit'>Search</button> </form> </div> ); } export default Search;
2. 修改服务端代码
- 删除原有的
app.get('/user/:name')路由 - 添加新的搜索路由,通过查询参数获取关键词并实现MongoDB模糊查询:
const express = require('express'); // 修正拼写错误:expres → express const cors = require('cors'); const { MongoClient, ServerApiVersion, ObjectId } = require('mongodb'); const app = express(); const port = process.env.PORT || 5000; app.use(cors()); app.use(express.json()) const uri = "mongodb+srv://user:#@cluster0.moilkdv.mongodb.net/?retryWrites=true&w=majority"; const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true, serverApi: ServerApiVersion.v1 }); async function run() { try { const userCollection = client.db('simpleNode').collection('users'); // 获取所有用户 app.get('/user', async (req, res) => { const cursor = userCollection.find({}); const users = await cursor.toArray(); res.send(users); }) // 获取单个用户用于更新 app.get('/user/:id', async (req, res) => { const updateId = req.params.id; const updateQuery = { _id: ObjectId(updateId)} const user = await userCollection.findOne(updateQuery); res.send(user); }) // 更新用户 app.put('/user/:id', async (req, res) => { const userId = req.params.id; const user = req.body; const filter = { _id: ObjectId(userId) }; const options = { upsert: true }; const updatedUser = { $set: { name: user.name, address: user.address } } const result = await userCollection.updateOne(filter, updatedUser, options); res.send(result); }) // 创建用户 app.post('/user', async (req, res) => { console.log('post api called'); const Nuser = req.body; const result = await userCollection.insertOne(Nuser); res.send(result); }); // 新增:搜索用户(使用查询参数) app.get('/user/search', async (req, res) => { const searchName = req.query.name; // 模糊匹配,不区分大小写 const searchQuery = { name: { $regex: searchName, $options: 'i' } }; const matchedUsers = await userCollection.find(searchQuery).toArray(); res.send(matchedUsers); }) // 删除用户 app.delete('/user/:id', async(req, res) => { const userId = req.params.id; const deleteQuery = { _id: ObjectId(userId)}; const result = await userCollection.deleteOne(deleteQuery); console.log("Delete complete of: ", userId); console.log(result); res.send(result); }) } finally { } } run().catch(console.dir); app.get('/', (req, res) => { res.send('Server is running'); }) app.listen(port);
额外修正
服务端代码存在拼写错误:const expres = require('express');需改为const express = require('express');,否则会导致express模块无法正确加载。
内容的提问来源于stack exchange,提问作者Bs Joy
相关产品推荐
相关产品推荐

