Node.js $lookup on ObjectId';对象数组中的s(猫鼬)

Node.js $lookup on ObjectId';对象数组中的s(猫鼬),node.js,mongodb,express,mongoose,Node.js,Mongodb,Express,Mongoose,我有两种模式: module.exports = mongoose.model('Article', { title : String, text : String, lang : { type: String, default: 'en'}, user : { type : mongoose.Schema.Types.ObjectId, ref: 'User' }, }); var userSchema = mongoose.Schema({ email : String,

我有两种模式:

module.exports = mongoose.model('Article', {
title : String,
text : String,
lang : { type: String, default: 'en'},
user : { type : mongoose.Schema.Types.ObjectId, ref: 'User' },
});



var userSchema = mongoose.Schema({
email        : String,
name         : String,
rating       : [{
                    _id: false,
                    articleID: {type: mongoose.Schema.Types.ObjectId, ref: 'Article'},
                    rate: Number
                }]
});
module.exports = mongoose.model('User', userSchema);
我想计算一个用户的平均评分(其文章的所有评分的平均值)

我试过这个:

User.aggregate([
            { $unwind: "$rating" },
            {
                "$lookup": {
                    "from": "Article",
                    "localField": "rating.articleID",
                    "foreignField": "_id",
                    "as": "article-origin"
                }
            }//,
            //{ $match: { "article-origin.user" : mongoose.Types.ObjectId(article.user) } }//,
            //{ $group : {_id : "$rating.articleID", avgRate : {  $avg : "$rating.rate" } } }
        ]).exec(function (err,result) {
            console.log(err);
            console.log(JSON.stringify(result));
        });
但是如果没有成功,锁定总是返回字段项目原点null

结果:
{u id:“590747e1af02570769c875dc”,“姓名:”“姓名”,“电子邮件:”“电子邮件”,“评级:{“评级”:5,“文章id:”59074a357fe6a307981e7925“}”,“文章来源:[]}


为什么不起作用?

当然不需要操作符,因为组聚合操作不使用
文章
集合中的文档,它只需要一个字段,即
文章ID
进行分组

有两种方法可以做到这一点。如果您的MongoDB服务器版本为3.4或更高版本,则可以在此处应用运算符来计算平均值,而无需重新计算 首先展平分级阵列,如果阵列较大,这可能会对性能产生一些影响

考虑运行以下管道:

User.aggregate([
    { "$match": { "_id" : mongoose.Types.ObjectId(article.user) } },
    {
        "$addFields": {
            "avgRate": {
                "$divide": [
                    {
                        "$reduce": {
                            "input": "$rating",
                            "initialValue": 0,
                            "in": { "$sum": ["$$value", "$$this.rate"] }
                        }
                    },
                    {
                        "$cond": [
                            { "$ne": [{ "$size": "$rating" }, 0] },
                            { "$size": "$rating" },
                            1
                        ]
                    }
                ]
            }
        }
    }
]).exec(function (err, result) {
    console.log(err);
    console.log(JSON.stringify(result));
});

如果使用MongoDB 3.2版,则首先需要评级数组:

User.aggregate([
    { "$match": { "_id" : mongoose.Types.ObjectId(article.user) } },
    { "$unwind": "$rating" },
    {
        "$group": {
            "_id": "$_id",
            "avgRate": { "$avg": "$rating.rate" }
        }
    }
]).exec(function (err, result) {
    console.log(err);
    console.log(JSON.stringify(result));
});

如果出于某种原因需要操作,则需要引用集合名称,而不是模型名称,因此应该使用正确的聚合操作

User.aggregate([
    { "$unwind": "$rating" },
    {
        "$lookup": {
            "from": "articles", /* collection name here, not model name */
            "localField": "rating.articleID",
            "foreignField": "_id",
            "as": "article-origin"
        }
    },
    { "$match": { "article-origin.user" : mongoose.Types.ObjectId(article.user) } },
    {
        "$group": {
            "_id": "$_id",
            "avgRate": { "$avg": "$rating.rate" }
        }
    }
]).exec(function (err, result) {
    console.log(err);
    console.log(JSON.stringify(result));
});