如何在猫鼬的路由器中等待函数完成其所有内部表达式?

Posted

技术标签:

【中文标题】如何在猫鼬的路由器中等待函数完成其所有内部表达式?【英文标题】:How to wait for a function to finish with all its inside expressions, in router in mongoose? 【发布时间】:2021-11-05 10:03:34 【问题描述】:

我只想改变数组中所有对象的键值

我真正想要的-

我从数据库中查询到的对象是-


  _id: 61389277fa5c742caf959885,
  title: 'What is GRE?',
  forumTab: 'GRE',
  askedAt: 2021-09-08T10:37:43.979Z,
  askedBy: 
    _id: 60f0a6a9b4259f7ef9c49cc8,
  

我想在askedBy 键中添加更多键值对,方法是再次使用给定的_id 查询数据库中的User

现在,被查询的用户对象是 -


  role: 'student',
  _id: 60f0a6a9b4259f7ef9c49cc8,
  firstName: 'Rishav',
  lastName: 'Raj'

最后我想返回下面的对象作为响应-


  _id: 61389277fa5c742caf959885,
  title: 'What is GRE?',
  forumTab: 'GRE',
  askedAt: 2021-09-08T10:37:43.979Z,
  askedBy: 
    _id: 60f0a6a9b4259f7ef9c49cc8,
    role: 'student',
    firstName: 'Rishav',
    lastName: 'Raj'
  

我正在创建一个新数组 questionsToSend 并使用更新的键值对推送对象顺序渲染,即使在以正确的顺序渲染函数之后为什么新数组questionsToSend在返回响应之前没有填充对象?

router.get("/questions", async (req, res) => 
  if (!req.query.forumTab) return res.status(400).send("something went wrong");

  const page = parseInt(req.query.page) - 1;
  const perPage = parseInt(req.query.perPage);

  let questionsToSend = [];

  const func0 = async (callback) => 
    const questions = await Question.find( forumTab: req.query.forumTab )
      .sort( askedAt: -1 )
      .limit(perPage)
      .skip(perPage * page);
    console.log("xxxxxxx");
    callback(questions);
  ;

  const func1 = async (questions, callBack) => 
    questions.forEach(async (question) => 
      const askedUserData = await User.findById(question.askedBy._id);

      if (!askedUserData) 
        const index = questions.indexOf(question);
        questions.splice(index, 1);
        return;
      

      questionsToSend.push(
        ..._.pick(question, [
          "_id",
          "title",
          "askedAt",
          "tags",
        ]),
        askedUserData,
      );
      console.log(questionsToSend);
    );
    console.log("yyyyyyyy");
    callBack();
  ;

  func0(
    (questions) =>
      func1(questions, async () => 
        console.log("zzzzzzzz");
        res.status(200).send(questionsToSend);
      )
  );
);

【问题讨论】:

【参考方案1】:

我们可以使用聚合来实现这一点

Question.aggregate([
 
   $match:  forumTab: req.query.forumTab  
 , 
  
    $lookup:  
      from: 'users',
      localField: 'askedBy._id',
      foreignField: '_id',
      as: "user"
     
 ,
  $unwind: "$user",
  "$addFields": 
    "askedBy": 
      "$mergeObjects": ["$askedBy", "$user"]
     
    
  ,
   $project:  "user" : 0 ,
   $sort: "askedAt": -1,
   $skip: perPage * page,
   $limit: perPage,
])
    $match 用于应用过滤器 $lookup 用于对集合进行连接。我假设集合名称是用户。 $lookup 将匹配结果作为数组返回。使用 $unwind 将其转换为对象,因为我们只返回一个。 $addFields 和 $mergeObjects 正在合并现有的 askBy 字段和新的用户字段 使用 $project 从结果集中删除用户字段。 然后排序、跳过和限制。

【讨论】:

它返回的是完整的用户对象,如何应用选择过滤器来选择一些特定的键值对? 我知道了,我将在 $addFields 中解构 $user,谢谢 或者您也可以在项目运算符中将字段值设置为0。假设如果您不想要用户的名字,则将其 user.firstName 设置为 0 $project: user: firstName: 0, password: 0 有效

以上是关于如何在猫鼬的路由器中等待函数完成其所有内部表达式?的主要内容,如果未能解决你的问题,请参考以下文章

如何在猫鼬的嵌入式文档中填充字段?

如何在猫鼬的数组中使用不同类型的模式?

如何在猫鼬的集合中找到文档项的平均值?

如何使子文档在猫鼬的特定日期过期?

在猫鼬的子数组中获取具有匹配对象的对象

在猫鼬的子数组中获取具有匹配对象的对象