ModeMongoose's Async/Await с цепочкой заселенных мангустов

У меня много проблем с выполнением последовательных команд mongoose при использовании async/await. Просто await Model.find({}) Команда работает так, как можно было бы ожидать в асинхронной функции, но когда я цепочка найти команды с lean, populate, а также exec в целях большой популяции ( http://mongoosejs.com/docs/populate.html) я не могу запустить их в порядке, как мне хотелось бы.

const messageSchema = new Schema({
  ...
})
const Message = mongoose.model("message", messageSchema)

const chatSchema = new Schema({
  conversations: [{
      messages: [{ type: Schema.Types.ObjectId, ref: "message" }]
  }]
})
const Chat = mongoose.model("chat", phoneSchema)

console.log("11111111111")

const chat = await Chat.findOne({ ... })
  .lean()
  .populate({ path: "conversations" })
  .exec(async (err, docs) => {
    const options = {
      path: "conversations.messages",
      model: "message",
    }

    const result = await Chat.populate(docs, options,
      (e, foundChat) => foundChat)

    console.log("22222222222")

    return result
  })

console.log("333333333333")

Результат:

11111111
33333333
22222222

Желаемый результат:

111111111
222222222
333333333

2 ответа

Не уверен, почему, перепробовал много разных вещей, но это работает.

const chat = await Chat.findOne({ ... })
  .populate({
    path: "conversations.messages",
    model: "message",
  })
  .exec((error, foundChat) => foundChat)

Я чувствую, что ваш код имеет 2 проблемы:

  1. Вы не можете вызывать populate() после того, как используете опцию lean(). Lean() превращает возвращаемые объекты в обычные объекты javascript, а не в документы mongoose. Заполнение - это встроенный метод в мангусте, поэтому его можно использовать только в документах мангуста. Это не имеет ничего общего с вашим вопросом, но важно знать.

  2. Когда вы вызываете exec() для запроса и передаете обратный вызов в качестве параметра, он не возвращает обещание, и поэтому предложение 'await' не влияет на него. Вот почему ваша функция не ожидает разрешения Chat.findOne() и переходит прямо к последнему console.log. Следующее, вероятно, будет работать:

    const chat = await Chat.findOne({ ... })
     .populate({ path: "conversations" })
     .exec().then(async (docs) => {
       const options = {
         path: "conversations.messages",
         model: "message",
       }
    
       const result = await Chat.populate(docs, options)
    
       console.log("22222222222")
    
       return result
    

    })

Другие вопросы по тегам