如何替换 ObjectId 引用。与来自 MongoDB 的实际对象(最好在服务器端)?

Jar*_*ski 7 mongoose mongodb node.js express angularjs

这是主体对象的架构:

var newsSchema = new Schema({
    headline: String,
    paragraph: String,
    imgURI: String,
    imgThumbURI: String,
    imgCaption: String,
    addedOn: Date,
    addedBy: {
        type: ObjectID,
        ref: 'usr'
    }
});
var News = mongoose.model('news', newsSchema);
Run Code Online (Sandbox Code Playgroud)

...以及 addedBy 的架构:

var usr = new Schema({
    username: String,
    avatar: {
        type: ObjectID,
        ref: 'avtr'
    },
    href: String
});
var UserModel = mongoose.model('usr', usr);
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好。所有作品。然后在 Angular 客户端中,我检索了一个新闻对象,但 addedBy 值不是所需的对象,而是一个 ObjectId:

{
    "headline":"Shocking news from the Neverland!",
    ...
    "addedBy":"520e9aac9ca114914c000003", // <-- the offender!!
    "addedOn":"2013-08-16T21:33:32.294Z",
    "_id":"520e9aac9ca114914c000001",
    "__v":0
}
Run Code Online (Sandbox Code Playgroud)

当我想要这样的对象时:

{
    "headline":"Shocking news from the Neverland!",
    ...
    "addedBy":{
        "username":"Peter"
        "avatar":{
            "src":"../images/users/avatars/avatar1.png", 
            "ststus":"happy"}
        }
    "addedOn":"2013-08-16T21:33:32.294Z",
    "_id":"520e9aac9ca114914c000001",
    "__v":0
}
Run Code Online (Sandbox Code Playgroud)

所以是的,我希望在将主体对象发送到 angular 客户端之前,将所有(无论多深)嵌套的 ObjectId 替换为来自数据库的它们各自的对象。我正在构建的 API 很深很复杂,如果 Angular 客户端可以从我的 Express 服务器接收一个准备好被扔进作用域的对象,那就太好了。
如何更改以下“/新闻”路线:

app.get('/news', function(req, res, next){
    News.
        find().
        exec(function(err, nws){
            if(err) {res.writeHead(500, err.message)}
            res.send(nws);
        });
});
Run Code Online (Sandbox Code Playgroud)

为了实现这一点,所以我可以像这样从 angular 完全访问完整的(嵌套)对象:

angular.module('App', ['ngResource'])
    .controller('NewsCtrl', function($scope, $resource){
        var News = $resource('/news');
        var news = News.query();
        $scope.news = news;
    });
Run Code Online (Sandbox Code Playgroud)

然后在网站上访问这样的api:

<img class="avatar-img" src="{{ news[0].addedBy.avatar.src }}">
Run Code Online (Sandbox Code Playgroud)

我非常感谢你的时间,欢呼杰瑞德

Jon*_*iaz 6

正如@WiredPrairie 所说,您需要使用 populate 函数Populate Mongoose Documentation

您的查询应如下所示:

app.get('/news', function(req, res, next){
    News.
        find().
        populate("addedBy").
        exec(function(err, nws){
            if(err) {res.writeHead(500, err.message)}
            res.send(nws);
        });
});
Run Code Online (Sandbox Code Playgroud)

你可以用 populate 做很多不同的事情,例如只带上“ addedBy”文档的用户名字段,你可以做

populate("addedBy","username")
Run Code Online (Sandbox Code Playgroud)

或者如果你不想带一个特定的领域,做这样的事情:

populate("addedBy","-username")
Run Code Online (Sandbox Code Playgroud)