来自填充文档的Mongoose sum字段

时间:2018-03-16 21:08:31

标签: javascript node.js mongodb mongoose

我有两个模型:UserTrackUser可以为每个Track完成并获得积分。

用户架构:

let userSchema = new mongoose.Schema({
    name: {type: String, required: true},
    completedTracks: [{
        type: mongoose.Schema.ObjectId,
        ref: 'Track',
    }],
});

跟踪架构:

let trackSchema = new mongoose.Schema({
  points: {
    type: Number,
    default: 0,
  }
});

我正在User模型中存储对已完成曲目的引用。

我想要做的是查询多个用户,仅显示每个用户完成的 _id 轨道,并添加有关新score属性中得分的信息。

我想要实现的结果示例:

[
    {
        "completedTracks": [
            "5a9f14f18e04b3225953954c",
            "5aa5a8fa7367661c03f57a99",
            "5aa1aa5a7da9fd2946b01c04"
        ],
        "name": "Person 1",
        "score": 42,
        "id": "5aaab2c63d1a9d182b183a01"
    },
    {
        "completedTracks": [],
        "name": "Person 2",
        "score": 0,
        "id": "5aaab602c5bdc411d3cef3bd"
    }
]

我尝试创建会返回分数的虚拟内容,但由于user.completedTracks只是ObjectIds

而无效
userSchema.virtual('score').get(function() {
    return this.completedTracks.reduce((acc, doc) => acc + doc.points, 0);
});

1 个答案:

答案 0 :(得分:1)

您可以在3.4中尝试以下聚合。

$lookup查找已完成曲目的分数,然后$addFields返回一个总分积分的分数字段和$project除外,以从回复中删除查找数据字段。< / p>

UserModel.aggregate([
  {"$lookup":{
    "from":"tracks", // name of the foreign collection
    "localField":"completedTracks",
    "foreignField":"_id",
    "as":"lookup-data"
  }},
  {"$addFields":{
    "score":{
      "$sum":"$lookup-data.points"
    }
  }},
  {"$project":{"lookup-data":0}}
])