嵌套的Mongo调用Node/Express



我正在尝试构建一个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个选项:

  1. 使用";填充";在Mongoose中,您可以编辑您的Mongoose用户模型,以允许completedItems引用ItemsCollection,然后在查询用户时使用"填充";方法,mongoose将自动为您检索所需的项目。

    你可以做一些类似的事情:

    const userSchema = Schema({
    _id: Schema.Types.ObjectId,
    completedItems: [{ type: Schema.Types.ObjectId, ref: 'Items' }]
    });
    

    请注意,这里的Items指的是您给ItemsSchema的名称。

    查看文档以了解更多详细信息

  2. 在尝试查询ItemsCollection之前,首先检查completedItems数组的长度,类似于如果用户没有completedItemss,则不必查询ItemsCollection。

    做一些类似的事情:

    if(user.completedItems.length != 0)
    ItemsCollection.find({id: user.completedItems})
    
  3. 第三种选择是使用GeaphQL,这样你就可以检索所有需要的数据来做这样的事情:

    UsersCollection.find()
    .populate({
    path: 'ItemsList',
    model: 'Items'
    })
    

最新更新