如何在 2 个地图函数中等待并从 mongoDB 检索文档

Posted

技术标签:

【中文标题】如何在 2 个地图函数中等待并从 mongoDB 检索文档【英文标题】:How to await inside 2 map functions and retrieve documents from mongoDB 【发布时间】:2021-05-04 02:56:05 【问题描述】:

我需要对返回如下内容的 API 进行一些修改:

[
  
    "_id": "0000000000000000001",
    "name": "Random name",
    "categories": [
        "5eb8548330550e017f8902e6",
        "5eb2548630550e117f8909eb",
        "5eb6548930550e017f8909e9"
    ]
  ,
  ...,
]

每个结果的类别都作为其各自文档的 ID 返回。 我需要处理结果,以便每个对象的类别字段都有一个对象数组,并且每个对象都有其类别的 ID 和名称。 我举个例子说明结果应该是什么:

[
  
    "_id": "0000000000000000001",
    "name": "Random name",
    "categories": [
      "_id": "5eb8548330550e017f8902e6",
      "name": "Category 1",
      "_id": "5eb2548630550e117f8909eb",
      "name": "Category 2",
      "_id": "5eb6548930550e017f8909e9",
      "name": "Category 3",
    ]
  ,
  ...,
]

我需要使用普通的 JS 来做到这一点,到目前为止,这就是我所做的,但它返回一个未定义的数组:

const resultArray = await Promise.all(
  searchResults.map(async (item) => 
    item.categories.map(async (categoryId) => 
      return await CategoryType.find( _id: categoryId);
    );
  )
);

目前我正在尝试获取类别字段中每个 id 的每个类别文档。 我敢打赌,我得到一个未定义数组的原因是我以错误的方式处理异步,但不知道如何处理。

【问题讨论】:

【参考方案1】:

严格回答您的问题:您缺少同步(因为Array.prototype.map 'ignores' async):

const resultArray = await Promise.all(
  searchResults.map(async (item) => 
    const promises = item.categories.map(async (categoryId) => 
      // you dont want find, but findOne btw
      return await CategoryType.findOne( _id: categoryId);
    );
    const categories = await Promise.all(promises)
    item.categories = categories
    return item
  )
);

这可以简化为

const resultArray = await Promise.all(
  searchResults.map(async item => 
    item.categories = await Promise.all(item.categories.map(categoryId => 
      return CategoryType.findOne( _id: categoryId)
    ))
    return item
  )
);

但正确的做法可能是使用populate

const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/dummy')

const Category = mongoose.model('Category', 
  name:String,
, 'categories');
const X = mongoose.model('X', 
  name:String,
  categories: [type: mongoose.Types.ObjectId, ref: 'Category']
, 'xs');

;(async()=>
  try 
  mongoose.set('debug', true)

  const xs = await X.find().populate('categories')

  console.log('xs : ', xs[0])
   finally 
    mongoose.disconnect()
  
)()

顺便说一句,你会注意到,猫鼬在后台使用find( _id: $in:[]),它只发出一个请求(比你做多个findOne 更好)

【讨论】:

完美!非常感谢

以上是关于如何在 2 个地图函数中等待并从 mongoDB 检索文档的主要内容,如果未能解决你的问题,请参考以下文章

如何从 2 个集合中读取数据并从两个集合中保存数据并将其保存在 SpringBatch 的第 3 个集合中

如何创建值数组并从 PHP 调用 JavaScript 函数

如何建立注销用户的路由并从mongodb数据库中删除

无法在地图方法中等待承诺

如何在异步函数中处理多个等待

如何在python 2.7中使用pymongo进行多处理池