[英]Mongoose refs not populating json
我正在嘗試通過簡單的Express API學習MongoDB。 該API非常適合於獲取單個集合,但是當我嘗試使用mongoose ref
將多個集合組合到一個架構中時,我得到一個僅包含_id
字段的json響應。
這是Mongoose中的兩個模式:
var LinkSchema = require('./link.js');
var MyInfoSchema = new Schema({
name: String,
title: String,
links: [ LinkSchema ]
});
var AboutSchema = new Schema({
img: String,
description: String
});
這些在端點上分別調用它們的工作正常。
我想要一個將這兩個集合合並為一個json響應的端點。 因此,我使用ref
制作了此模型
var MyInfoSchema = require('./myinfo.js');
var AboutSchema = require('./about.js');
var AllDataSchema = new Schema({
myinfo: {
type: mongoose.Schema.ObjectId,
ref: 'MyInfoSchema'
},
about: {
type: mongoose.Schema.ObjectId,
ref: 'AboutSchema'
}
});
我的Express API路由如下所示
var router = express.Router();
router.route('/')
.get(function(request, response){
var data = new AllData();
// add myinfo
MyInfo.findOne(function(error, info){
data.myinfo = info;
console.log(data); // this gives an id
});
// add about
About.findOne(function(error, about){
data.about = about;
});
console.log(data); // this prints nothing
response.json(data);
});
但是,我得到的json響應只是一個_id
{ "_id": "59bfed783f0ba490a34c9ce9" }
為什么未填充響應?
我嘗試登錄到控制台。 當我將日志放入findOne()
,我得到了這樣的對象
{ _id: 59bfed783f0ba490a34c9ce9,
myinfo: 59b1ad02d551330000000002 }
當我將log語句放置在find函數之外並且在response.json()
之前時,我什么也沒得到。 這是為什么? data
仍應在范圍內,不是嗎?
編輯:
正如@Mikey在答案中所建議的那樣,我已經重構為使用Promises。 距離越來越近,但是有兩個問題。 1.每個集合的鍵都缺失,並且2.它正在為根結構而不是對象返回一個數組。
這是更新
.get(function(request, response){
var data = new AllData();
var p1 = MyInfo.findOne().exec(),
p2 = Navigation.findOne().exec(),
p3 = About.findOne().exec(),
p4 = Contact.findOne().exec();
Promise.all([p1, p2, p3, p4]).then(function(data) {
data.myinfo = data[0];
data.navigation = data[1];
data.about = data[2];
data.contact = data[3];
response.json(data);
});
});
這是回應
[
{
"_id": "59b1ad02d551330000000002",
"title": "Television Tester",
"name": "Walter P. K.",
"__v": 0,
"links": [
{
"name": "...",
"url": "...",
"_id": "59b1ad02d551330000000004"
},
{
"name": "more...",
"url": "more...",
"_id": "59b1ad02d551330000000003"
}
]
},
{
"_id": "59b2e606103ace0000000003",
"__v": 1,
"links": [
{
"name": "About",
"url": "#",
"_id": "59b2e62d103ace0000000009"
},
{
"name": "Stuff",
"url": "#",
"_id": "59b2e62d103ace0000000008"
},
{
"name": "Contact",
"url": "#",
"_id": "59b2e62d103ace0000000007"
}
]
}
...
]
應該是這樣的
{
myinfo: {}.
navigation: {},
about: {},
contact: {}
}
貓鼬操作是異步的。 您需要等待所有操作完成后才能發送響應。
您可以嵌套操作
router.route('/').get(function(request, response){
var data = new AllData();
MyInfo.findOne(function(err, info) {
data.myinfo = info;
About.findOne(function (err, about){
data.about = about;
response.json(data);
});
});
});
或使用諾言(我認為是這樣)
router.route('/').get(function(request, response){
var data = new AllData();
var p1 = MyInfo.findOne().exec(),
p2 = About.findOne().exec();
Promise.all([p1, p2]).then(function(data) {
data.myinfo = data[0];
data.about = data[1];
response.json(data);
});
});
findOne是異步的,因此您的控制台日志在findOne回調之前運行。
您可能正在尋找類似這樣的東西,它將查詢“ AllData”集合並將存儲的ID替換為引用的文檔中的“ myinfo”和“ about”:
AllData.find()
.populate('myinfo about')
.exec(function(error, docs) {
console.log(docs)
response.json(docs)
});
我能夠通過其他答復者的有用建議來解決該問題。 感謝您指出find()
和promises的異步特性。 我需要使其工作的是對響應結構(而不是Mongoose Schema)使用普通的JS對象,並進行一些變量名清除。 在Mikey的答案中,以及我對該問題的編輯中,返回的response和console.log數組實際上是promises數組(即p1,p2,p3等的值),而不是我想要返回的數據結構。
這是工作代碼:
router.route('/')
.get(function(request, response){
var p1 = MyInfo.findOne().exec(),
p2 = Navigation.findOne().exec(),
p3 = About.findOne().exec(),
p4 = Contact.findOne().exec();
Promise.all([p1, p2, p3, p4]).then(function(docs) {
var data = {};
console.log(docs);
data.myinfo = docs[0];
data.navigation = docs[1];
data.about = docs[2];
data.contact = docs[3];
response.json(data);
});
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.