我正在尝试构建一个REST api,该api由一个单独的React前端使用。在一个页面上,我需要在一个mongo数据库中从不同的集合中提取数据,并在将响应返回到前端之前将其捆绑在一起,以最大限度地减少api调用。我的数据库中有以下集合:
- 用户
- 项目
其中每个的数据结构如下:
- 用户集合=
[{id: ObjectId, completedItems=[ObjectId, ObjectId, ...], ...}]
- ItemsCollection=
[{id: ObjectId, name: string, ...}]
在我的node/express应用程序中,我想调用以获取所有用户,对于每个用户,在返回响应之前,查询项目集合以获取每个项目的名称。
当我最终返回响应时,我希望能够返回以下结构的对象,但不改变存储数据的结构。
响应=[{id: ObjectId, completedItems=[{id: ObjectId, name: string}, {id: ObjectId, name: string}]}]
我遇到的问题是,当我进行此调用时,当用户的completedItems数组中没有项目时,当它尝试进行第二次api调用时,整个后端都会崩溃,我最终会收到错误消息,如";无法读取null的属性"name";。
我想我在这里错过了某种错误处理,或者我没有以正确的方式思考整体结构。
由于这是我的第一个主要RESTapi,我不知道我是否应该在返回响应之前尝试在后端合并这些信息,或者我是否应该处理前端的信息,向前端返回用户调用的响应,然后对后端进行第二次api调用以获取项数据。
任何指导都将不胜感激!
''lang-js
const getUsers = async (req, res, next) => {
let users
try {
users = await User.find({}, {name:1, items: 1})
} catch (err) {
return next(new Error('Could not fetch inductions').code(500))
}
for (let i in users){
let {id, name, items} = users[i]
item = await Item.findById(item, {name:1})
}
users[i] = {
id: id, name: name, item: {
name: item.name, id: item.id
}
}
}
''
我建议3个选项:
-
使用";填充";在Mongoose中,您可以编辑您的Mongoose用户模型,以允许completedItems引用ItemsCollection,然后在查询用户时使用"填充";方法,mongoose将自动为您检索所需的项目。
你可以做一些类似的事情:
const userSchema = Schema({ _id: Schema.Types.ObjectId, completedItems: [{ type: Schema.Types.ObjectId, ref: 'Items' }] });
请注意,这里的Items指的是您给ItemsSchema的名称。
查看文档以了解更多详细信息
-
在尝试查询ItemsCollection之前,首先检查completedItems数组的长度,类似于如果用户没有completedItemss,则不必查询ItemsCollection。
做一些类似的事情:
if(user.completedItems.length != 0) ItemsCollection.find({id: user.completedItems})
-
第三种选择是使用GeaphQL,这样你就可以检索所有需要的数据来做这样的事情:
UsersCollection.find() .populate({ path: 'ItemsList', model: 'Items' })