我想汇总评分,以便我可以得到反馈的总数。但事实是,它被引用了。这是我的架构
用户
username: String,
fullname: String,
email: {
type: String,
lowercase: true,
unique: true
},
address: String,
password: String,
feedback: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Feedback'
}]
反馈
var FeedbackSchema = new mongoose.Schema({
postname: String,
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
message: String,
feedbacktype: String,
thumbsup: Boolean,
rating: {
communication: Number,
timeliness: Number,
delivery: Number
}
});
所以我想要实现的是,我将通过id找到用户,然后填充反馈字段,然后我将汇总反馈字段的评级,这样我就可以获得通信,交付和为了及时。 (评分为1-5星)
你知道如何聚合和填充吗?谢谢
**更新
所以我将聚合运行到用户架构,现在我从所有评级中得到0结果
User.aggregate([
{ "$match": { "_id": ObjectId('593150f6ac4d9b0410d2aac0') } },
{ "$lookup": {
"from": "feedbacks",
"localField": "feedback",
"foreignField": "_id",
"as": "feedback"
}},
{ "$project": {
"username": 1,
"fullname": 1,
"email": 1,
"password": 1,
"rating": {
"communication": { "$sum": "$feedback.rating.communication" },
"timeliness": { "$sum": "$feedback.rating.timeliness" },
"delivery": { "$sum": "$feedback.rating.delivery" }
}
}}
]).exec(function(err, a){
console.log(a)
})
结果rating: { communication: 0, timeliness: 0, delivery: 0 } } ]
也尝试过与其他用户一起使用,所有这些都是0结果评级
答案 0 :(得分:1)
var async = require('async'),
mongoose = require('mongoose'),
Schema = mongoose.Schema;
mongoose.connect('mongodb://localhost/rating');
var userSchema = new Schema({
username: String,
feedback: [{ type: Schema.Types.ObjectId, ref: 'Feedback' }]
});
var feedbackSchema = new Schema({
rating: {
communication: Number,
timeliness: Number,
delivery: Number
}
});
var User = mongoose.model('User', userSchema);
var Feedback = mongoose.model('Feedback', feedbackSchema);
async.series(
[
(callback) => {
async.each([User,Feedback],(model,callback) => {
model.remove({},callback);
},callback);
},
(callback) => {
async.waterfall(
[
(callback) => {
async.map(
[
{ "rating": {
"communication": 1, "timeliness": 2, "delivery": 3
}},
{ "rating": {
"communication": 2, "timeliness": 3, "delivery": 4
}}
],
(item,callback) => {
Feedback.create(item,callback)
},
callback
);
},
(feedback, callback) => {
User.create({ "username": "Bill", "feedback": feedback },callback);
},
(user, callback) => {
User.aggregate([
{ "$match": { "_id": user._id } },
{ "$lookup": {
"from": "feedbacks",
"localField": "feedback",
"foreignField": "_id",
"as": "feedback"
}},
{ "$project": {
"username": 1,
"rating": {
"communication": { "$sum": "$feedback.rating.communication" },
"timeliness": { "$sum": "$feedback.rating.timeliness" },
"delivery": { "$sum": "$feedback.rating.delivery" }
}
}}
],(err,results) => {
console.log(JSON.stringify(results, undefined, 2));
callback(err);
});
}
],
callback
)
}
],
(err) => {
if (err) throw err;
mongoose.disconnect();
}
);
这将创建两个集合作为用户
{
"_id" : ObjectId("593548455198ab3c09cf736b"),
"username" : "Bill",
"feedback" : [
ObjectId("593548455198ab3c09cf7369"),
ObjectId("593548455198ab3c09cf736a")
],
"__v" : 0
}
反馈:
{
"_id" : ObjectId("593548455198ab3c09cf7369"),
"rating" : {
"communication" : 1,
"timeliness" : 2,
"delivery" : 3
},
"__v" : 0
}
{
"_id" : ObjectId("593548455198ab3c09cf736a"),
"rating" : {
"communication" : 2,
"timeliness" : 3,
"delivery" : 4
},
"__v" : 0
}
节目输出显示聚合:
[
{
"_id": "5935494a159c633c1b34807b",
"username": "Bill",
"rating": {
"communication": 3,
"timeliness": 5,
"delivery": 7
}
}
]
如果两个依赖关系不够清楚,还要package.json
:
{
"name": "ratings",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"async": "^2.4.1",
"mongoose": "^4.10.4"
}
}
就我个人而言,我会从"反馈"因为你已经在那里记录了用户,实际上这种方式可以更好地扩展。
我们可以使用$lookup
而不是使用填充,而是使用至少为3.2的MongoDB服务器版本:
Feedback.aggregate([
{ "$match": { "user": userId } },
{ "$group": {
"_id": "$user",
"communication": { "$sum": "$rating.communication" },
"timeliness": { "$sum": "$rating.timeliness" },
"delivery": { "$sum": "$rating.delivery" }
}},
{ "$lookup": {
"from": "users",
"localField": "_id",
"foreignField": "_id",
"as": "user"
}},
{ "$unwind": "$user" }
])
如果您没有支持$lookup
的服务器版本,那么您仍然可以"手动加入"用户详细信息如下:
Feedback.aggregate([
{ "$match": { "user": userId } },
{ "$group": {
"_id": "$user",
"communication": { "$sum": "$rating.communication" },
"timeliness": { "$sum": "$rating.timeliness" },
"delivery": { "$sum": "$rating.delivery" }
}}
],function(err, results) {
result = results[0];
User.findById(userId).lean().exec(function(err, user) {
result.user = user; // swap the _id for the Object
// Then output result
});
})
这基本上是.populate()
的作用,但我们正在为返回的结果手动有效地进行此操作。
您可以使用User
模型进行相反的工作,但这样做可能更有效率。
User.aggregate([
{ "$match": { "_id": userid } },
{ "$lookup": {
"from": "feedbacks",
"localField": "feedback",
"foreignField": "_id",
"as": "feedback"
}},
{ "$project": {
"username": 1,
"fullname": 1,
"email": 1,
"password": 1,
"rating": {
"communication": { "$sum": "$feedback.rating.communication" },
"timeliness": { "$sum": "$feedback.rating.timeliness" },
"delivery": { "$sum": "$feedback.rating.delivery" }
}
}}
])