MongoDB双集合关联:如何根据餐厅dishes外键获取菜品及配置前端Fetch?
获取指定餐厅的关联菜品对象
一、后端接口设计与实现
首先需要在后端新增接口,用于根据餐厅ID查询其关联的菜品。以下是Node.js + Express + MongoDB的实现示例:
方式1:分步查询
const { ObjectId } = require('mongodb'); const express = require('express'); const app = express(); // 假设已连接MongoDB,db为数据库实例 app.get('/api/restaurants/:restaurantId/dishes', async (req, res) => { try { const { restaurantId } = req.params; // 查询指定餐厅 const restaurant = await db.collection('restaurants').findOne({ _id: ObjectId(restaurantId) }); if (!restaurant) { return res.status(404).json({ message: '餐厅不存在' }); } // 根据餐厅的dishes外键数组查询对应菜品 const dishIds = restaurant.dishes.map(id => ObjectId(id)); const dishes = await db.collection('dishes').find({ _id: { $in: dishIds } }).toArray(); res.json(dishes); } catch (err) { res.status(500).json({ message: '服务器错误', error: err.message }); } });
方式2:使用MongoDB聚合查询(更高效)
const { ObjectId } = require('mongodb'); const express = require('express'); const app = express(); app.get('/api/restaurants/:restaurantId/dishes', async (req, res) => { try { const { restaurantId } = req.params; // 用$lookup关联两个集合 const [result] = await db.collection('restaurants').aggregate([ { $match: { _id: ObjectId(restaurantId) } }, { $lookup: { from: 'dishes', // 关联的集合名 localField: 'dishes', // 餐厅集合中存储外键的字段 foreignField: '_id', // 菜品集合中对应的主键字段 as: 'restaurantDishes'// 输出的字段名 } }, { $project: { restaurantDishes: 1, _id: 0 } } // 只返回菜品数据 ]).toArray(); if (!result) { return res.status(404).json({ message: '餐厅不存在' }); } res.json(result.restaurantDishes); } catch (err) { res.status(500).json({ message: '服务器错误', error: err.message }); } });
二、前端Fetch请求调整
前端需要先获取到指定餐厅的ID(比如从餐厅列表接口、路由参数或页面交互中获取),然后构造正确的请求URL:
// 封装获取餐厅菜品的函数,传入餐厅ID作为参数 const fetchRestaurantDishes = async (restaurantId) => { try { // 拼接包含餐厅ID的请求URL const url = `http://localhost:3001/api/restaurants/${restaurantId}/dishes`; const response = await fetch(url); if (!response.ok) { throw new Error(`请求失败,状态码:${response.status}`); } const dishes = await response.json(); console.log('餐厅菜品:', dishes); return dishes; } catch (error) { console.error('获取菜品出错:', error); throw error; } }; // 调用示例:传入目标餐厅的ID fetchRestaurantDishes("63a877556959f4b58c5042cf");
说明
- 如果是从餐厅列表进入详情页,可以在点击餐厅时将该餐厅的
_id传递给这个函数; - 如果是单页应用,也可以从路由参数中读取餐厅ID(比如
/restaurants/:id中的id)。
内容的提问来源于stack exchange,提问作者abeer
相关产品推荐
相关产品推荐

