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 проблемы:
Вы не можете вызывать populate() после того, как используете опцию lean(). Lean() превращает возвращаемые объекты в обычные объекты javascript, а не в документы mongoose. Заполнение - это встроенный метод в мангусте, поэтому его можно использовать только в документах мангуста. Это не имеет ничего общего с вашим вопросом, но важно знать.
Когда вы вызываете 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
})