【问题标题】:async foreach and mongoose in nodejsnodejs中的异步foreach和mongoose
【发布时间】:2021-04-08 09:39:37
【问题描述】:

在猫鼬中,我建立了类似于猫鼬文档的关系,现在我想要一个对象数组

对象是我们拥有的对象的子对象

例如在 tweeter 中,一个用户有很多推文,每条推文都有标题、内容和作者

有人给我们用户 ID,我们给他所有推文用户的标题和内容数组

[
{title: 'title01', content: 'aaaaaa'},
{title: 'title02', content: 'bbbbb'},
.
.
.
]

我试试

    const username = req.params.username;
    User.find({ username: username }, (err, docs) => {
      if (err) return res.json({ err: true });
      if (docs.length > 0) {
        let lives: Array<Object> = [];
        docs[0].lives.forEach((live, idx) => {
          Live.find({ _id: live }, (err, docs) => {
            lives.push(docs[0]);
          });
        });
      } else {
        return res.json({ err: true });
      }
    });

lives 有标题内容和作者(在 DB 中我将其命名为用户) 但是因为 aSync 我无法在 forEach 之后获得生命 :)

更新:

直播模式:

const schema = new mongoose.Schema({
  title: {
    type: String,
    required: true,
  },
  content: {
    type: String,
    required: true,
  },
  user: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "users",
    required: true,
  },
});

用户模式:

import { ArraySortOptions } from "joi";
import mongoose, { Model } from "mongoose";

interface IUser extends mongoose.Document {
  email: string;
  username: string;
  password: string;
  lives: Array<mongoose.Schema.Types.ObjectId>;
}

const schema: mongoose.Schema = new mongoose.Schema({
  username: {
    type: String,
    required: true,
  },
  password: {
    type: String,
    required: true,
  },
  email: {
    type: String,
    required: true,
  },
  lives: [
    {
      type: mongoose.Schema.Types.ObjectId,
      ref: "lives",
    },
  ],
});
const User: Model<IUser> = mongoose.model("users", schema);
export default User;

【问题讨论】:

    标签: node.js mongodb asynchronous mongoose foreach


    【解决方案1】:

    我会这样做:

    const username = req.params.username;
    User.find({ username: username }, async (err, docs) => {
      if (err) return res.json({ err: true });
      if (docs.length > 0) {
        // start with asnyc queries
        let livePromises = [];
        for (let live of docs[0].lives) {
          // push new promise which resolves the docs[0] of this live id
          livePromises.push(new Promise(resolve => {
            Live.find({ _id: live }, (err, docs) => {
              resolve(docs[0]);
            });
          }
        }
        // await all query results parallel
        let lives = await Promise.all(livePromises);
        // use lives variable as you want
        return res.json({ lives: lives });
      } else {
        return res.json({ err: true });
      }
    });
    

    我不确定你使用的是哪种类型的系统(你写了lives: Array&lt;Object&gt;),所以我跳过了。根据需要修改我的建议。
    如果您对此答案或一般Promises 有任何疑问,请写评论。

    【讨论】:

    • 我用打字稿
    • Promise.all 做什么?
    • Promise.all() 方法将一个可迭代的 Promise 作为输入,并返回一个 Promise,该 Promise 解析为输入 Promise 的结果数组。
    【解决方案2】:

    最好使用 Mongoose 的内置 populate() 方法,该方法允许您引用其他集合中的文档,类似于 MongoDB 版本 >= 3.2 中的类似联接的 $lookup 聚合运算符。

    由于populate() 需要附加查询,因此使用User.findOne() 查询与我们在参数中提供的用户名匹配的单个用户。

    使用 async/await 可以如下完成:

    const { username } = req.params;
    const user = await User.findOne({ username }).populate('lives');
    console.log(user.lives); // ---> [{title: 'title01', content: 'aaaaaa'}, { ... }]
    

    【讨论】:

      猜你喜欢
      • 2020-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-25
      相关资源
      最近更新 更多