合并集合以获得平均评级,但在给出评级之前仍然获得所有原始集合。猫鼬/节点
Merge collections to get average rating, but still get all of original collection before a rating has been given. Mongoose / nodejs
我有一个创建项目(波本威士忌)的管理员,用户可以在该评论中发表评论和评分。我能够汇总评论,但无法显示新创建的波旁威士忌,只能显示那些已经播种且已经有评级的波旁威士忌。我试图实现类似于此线程的东西:,但我没有做正确的事情。
我是菜鸟,主要玩前端,很迷茫如何把这个示例代码改成实际的生产代码。我看到每个功能在做什么,但仍然模糊不清。
我是否应该执行 async.each 并将聚合函数设置为迭代器..?我知道这是坏了。我现在已经尝试了一些东西。不断收到 500 错误,console.log 上什么也没有。对这个菜鸟的任何帮助,非常感谢。
这是我的架构:
波旁威士忌:
'use strict';
var mongoose = require('mongoose'),
BourbonSchema = null;
module.exports = mongoose.model('Bourbon', {
name: {type: String, required: true},
blog: {type: String, required: true},
photo: {type: String, required: true, default:'http://aries-wineny.com/wp-content/uploads/2014/09/woodford-reserve.jpg'},
location: {type: String, required: true},
distillery: {type: String, required: true},
avgRating: {type: Number}
});
var Bourbon = mongoose.model('Bourbon', BourbonSchema);
module.exports = Bourbon;
评论:
'use strict';
var mongoose = require('mongoose');
module.exports = mongoose.model('Comment', {
bourbonId: {type: mongoose.Schema.ObjectId, ref: 'Bourbon'},
userId: {type: mongoose.Schema.ObjectId, ref: 'User'},
text: {type: String, required: true},
createdAt: {type: Date, required: true, default: Date.now},
rating : {type: Number, required: true},
votes: {type: Number, default: 0}
});
这是我在控制器中的查找/获取,我尝试从引用的 link 拼凑起来,但现在很草率:
'use strict';
var Bourbon = require('../../../models/bourbon'),
Comment = require('../../../models/comment'),
DataStore = require('nedb'),
db = new DataStore(),
async = require('async');
module.exports = {
description: 'Get Bourbons',
notes: 'Get Bourbons',
tags: ['bourbons'],
handler: function(request, reply){
async.waterfall(
[
function(comment,callback){
async.series(
[
function(callback){
Bourbon.find({},function(err,results){
async.eachLimit(results,10,function(result,callback){
db.insert({
'bourbonId': result._id.toString(),
'location' : result.location,
'blog' : result.blog,
'distillery': result.distillery,
'name': result.name,
'avgRating': 0
},callback);
},callback);
});
},
function(callback){
Comment.aggregate(
[
{'$group':{
'_id': '$bourbonId',
'avgRating':{
'$avg':'$rating'
}
}}
],
function(err,results){
async.eachLimit(results,10,function(result,callback){
db.update(
{'bourbonId': result._id.toString()},
{'$set':{
'avgRating': result.avgRating
}
},
callback
);
},callback);
}
);
}
],
function(err) {
if (err) callback(err);
db.find({},{'_id': 0},callback);
}
);
}
],
function(err,results){
reply({results: results});
console.log('LOOOOOOOOOOOOOOOOK',JSON.stringify(results, undefined, 4));
process.exit();
});
}
};
看来您还有更多关于回调和排序的知识要学习。这是您需要的请求处理程序中的所有代码。当然,当您看到正在发生的事情时更改为发送响应。
async.series(
[
// List out exiting collection with 0 average
function(callback) {
Bourbon.find({},function(err,results){
async.eachLimit(results,10,function(result,callback){
var plain = result.toObject()
plain.bourbonId = plain._id.toString();
plain.avgRating = 0;
delete plain._id;
db.insert(plain,callback); // next each iteration
},callback); // move to next in series
});
},
// Get aggregate results and update the items you just wrote
function(callback) {
Comment.aggregate(
[
{ '$group': {
'_id': '$bourbonId',
'avgRating':{ '$avg':'$rating' }
}}
],
function(err,results) {
async.eachLimit(results,10,function(result,callback){
db.update(
{ 'bourbonId': result._id.toString() },
{'$set': {'avgRating': result.avgRating } },
callback // next each iteration
);
},callback); // next in series "last"
}
);
}
],
// This is called when both in the series are complete
function(err) {
if (err) callback(err);
db.find({},{'_id': 0},function(err,docs) {
console.log( docs );
});
}
);
这里的目的是:
- 将 0 个值放入所有项目的散列 table(此处使用 nedb)
- 从其他集合获取聚合结果
- 用实际具有值的项目更新所有项目的副本
- 当一切都完成后,你读回你的散列table
完整的工作示例:
var async = require('async'),
mongoose = require('mongoose'),
DataStore = require('nedb'),
db = new DataStore(),
Schema = mongoose.Schema;
var userSchema = new Schema({
"name": String
});
var ratingSchema = new Schema({
"bourbonId": { "type": Schema.Types.ObjectId, "ref": "Bourbon" },
"userId": { "type": Schema.Types.ObjectId, "ref": "User" },
"rating": { "type": Number, "required": true }
});
var bourbonSchema = new Schema({
"name": { "type": String, "required": true },
"blog": { "type": String, "required": true },
"photo": { "type": String, "required": true },
"ratings": [{ "type": Schema.Types.ObjectId, "ref": "Rating" }],
"rating": { "type": Number }
});
var User = mongoose.model( "User", userSchema ),
Rating = mongoose.model( "Rating", ratingSchema ),
Bourbon = mongoose.model( "Bourbon", bourbonSchema );
mongoose.connect("mongodb://localhost/bourbon");
async.waterfall(
[
function(callback) {
async.each([User,Rating,Bourbon],function(model,callback) {
model.remove({},callback);
},
function(err) {
callback(err);
});
},
function(callback) {
Bourbon.create({
"name": 'test',
"blog": 'test',
"photo": 'test'
},callback);
},
function(bourbon,callback) {
Bourbon.create({
"name": 'another',
"blog": 'another',
"photo": 'another'
},callback);
},
function(bourbon,callback) {
User.create({ "name": 'ted' },function(err,user) {
if (err) callback(err);
Rating.create({
"bourbonId": bourbon,
"userId": user,
"rating": 5
},function(err,rating1) {
callback(err,user,bourbon,rating1)
});
});
},
function(user,bourbon,rating1,callback) {
Rating.create({
"bourbonId": bourbon,
"userId": user,
"rating": 7
},function(err,rating2) {
callback(err,bourbon,rating1,rating2);
});
},
function(bourbon,rating1,rating2,callback) {
Bourbon.findById(bourbon.id,function(err,bourbon) {
bourbon.ratings.push(rating1,rating2);
bourbon.save(function(err,bourbon) {
callback(err)
});
});
},
function(callback) {
async.series(
[
function(callback) {
Bourbon.find({},function(err,results) {
if (err) callback(err);
async.eachLimit(results,10,function(result,callback) {
var plain = result.toObject();
plain.bourbonId = plain._id.toString();
plain.avgRating = 0;
delete plain._id;
db.insert(plain,callback);
},callback);
});
},
function(callback) {
Rating.aggregate(
[
{ "$group": {
"_id": "$bourbonId",
"avgRating": { "$avg": "$rating" }
}}
],
function(err,results) {
if (err) callback(err);
async.eachLimit(results,10,function(result,callback) {
db.update(
{ "bourbonId": result._id.toString() },
{ "$set": { "avgRating": result.avgRating } },
callback
);
},callback);
}
);
}
],
function(err) {
if (err) callback(err);
db.find({},{ '_id': 0 },callback);
}
);
}
],
function(err,results) {
if (err) throw err;
console.log( results );
mongoose.disconnect();
}
);
Returns 结果符合预期:
[ { name: 'test',
blog: 'test',
photo: 'test',
__v: 0,
ratings: [],
bourbonId: '54c17bea8aa5f8c9161f5b6e',
avgRating: 0 },
{ name: 'another',
blog: 'another',
photo: 'another',
__v: 1,
ratings: [ [Object], [Object] ],
bourbonId: '54c17bea8aa5f8c9161f5b6f',
avgRating: 6 } ]
我有一个创建项目(波本威士忌)的管理员,用户可以在该评论中发表评论和评分。我能够汇总评论,但无法显示新创建的波旁威士忌,只能显示那些已经播种且已经有评级的波旁威士忌。我试图实现类似于此线程的东西:
我是菜鸟,主要玩前端,很迷茫如何把这个示例代码改成实际的生产代码。我看到每个功能在做什么,但仍然模糊不清。
我是否应该执行 async.each 并将聚合函数设置为迭代器..?我知道这是坏了。我现在已经尝试了一些东西。不断收到 500 错误,console.log 上什么也没有。对这个菜鸟的任何帮助,非常感谢。
这是我的架构: 波旁威士忌:
'use strict';
var mongoose = require('mongoose'),
BourbonSchema = null;
module.exports = mongoose.model('Bourbon', {
name: {type: String, required: true},
blog: {type: String, required: true},
photo: {type: String, required: true, default:'http://aries-wineny.com/wp-content/uploads/2014/09/woodford-reserve.jpg'},
location: {type: String, required: true},
distillery: {type: String, required: true},
avgRating: {type: Number}
});
var Bourbon = mongoose.model('Bourbon', BourbonSchema);
module.exports = Bourbon;
评论:
'use strict';
var mongoose = require('mongoose');
module.exports = mongoose.model('Comment', {
bourbonId: {type: mongoose.Schema.ObjectId, ref: 'Bourbon'},
userId: {type: mongoose.Schema.ObjectId, ref: 'User'},
text: {type: String, required: true},
createdAt: {type: Date, required: true, default: Date.now},
rating : {type: Number, required: true},
votes: {type: Number, default: 0}
});
这是我在控制器中的查找/获取,我尝试从引用的 link 拼凑起来,但现在很草率:
'use strict';
var Bourbon = require('../../../models/bourbon'),
Comment = require('../../../models/comment'),
DataStore = require('nedb'),
db = new DataStore(),
async = require('async');
module.exports = {
description: 'Get Bourbons',
notes: 'Get Bourbons',
tags: ['bourbons'],
handler: function(request, reply){
async.waterfall(
[
function(comment,callback){
async.series(
[
function(callback){
Bourbon.find({},function(err,results){
async.eachLimit(results,10,function(result,callback){
db.insert({
'bourbonId': result._id.toString(),
'location' : result.location,
'blog' : result.blog,
'distillery': result.distillery,
'name': result.name,
'avgRating': 0
},callback);
},callback);
});
},
function(callback){
Comment.aggregate(
[
{'$group':{
'_id': '$bourbonId',
'avgRating':{
'$avg':'$rating'
}
}}
],
function(err,results){
async.eachLimit(results,10,function(result,callback){
db.update(
{'bourbonId': result._id.toString()},
{'$set':{
'avgRating': result.avgRating
}
},
callback
);
},callback);
}
);
}
],
function(err) {
if (err) callback(err);
db.find({},{'_id': 0},callback);
}
);
}
],
function(err,results){
reply({results: results});
console.log('LOOOOOOOOOOOOOOOOK',JSON.stringify(results, undefined, 4));
process.exit();
});
}
};
看来您还有更多关于回调和排序的知识要学习。这是您需要的请求处理程序中的所有代码。当然,当您看到正在发生的事情时更改为发送响应。
async.series(
[
// List out exiting collection with 0 average
function(callback) {
Bourbon.find({},function(err,results){
async.eachLimit(results,10,function(result,callback){
var plain = result.toObject()
plain.bourbonId = plain._id.toString();
plain.avgRating = 0;
delete plain._id;
db.insert(plain,callback); // next each iteration
},callback); // move to next in series
});
},
// Get aggregate results and update the items you just wrote
function(callback) {
Comment.aggregate(
[
{ '$group': {
'_id': '$bourbonId',
'avgRating':{ '$avg':'$rating' }
}}
],
function(err,results) {
async.eachLimit(results,10,function(result,callback){
db.update(
{ 'bourbonId': result._id.toString() },
{'$set': {'avgRating': result.avgRating } },
callback // next each iteration
);
},callback); // next in series "last"
}
);
}
],
// This is called when both in the series are complete
function(err) {
if (err) callback(err);
db.find({},{'_id': 0},function(err,docs) {
console.log( docs );
});
}
);
这里的目的是:
- 将 0 个值放入所有项目的散列 table(此处使用 nedb)
- 从其他集合获取聚合结果
- 用实际具有值的项目更新所有项目的副本
- 当一切都完成后,你读回你的散列table
完整的工作示例:
var async = require('async'),
mongoose = require('mongoose'),
DataStore = require('nedb'),
db = new DataStore(),
Schema = mongoose.Schema;
var userSchema = new Schema({
"name": String
});
var ratingSchema = new Schema({
"bourbonId": { "type": Schema.Types.ObjectId, "ref": "Bourbon" },
"userId": { "type": Schema.Types.ObjectId, "ref": "User" },
"rating": { "type": Number, "required": true }
});
var bourbonSchema = new Schema({
"name": { "type": String, "required": true },
"blog": { "type": String, "required": true },
"photo": { "type": String, "required": true },
"ratings": [{ "type": Schema.Types.ObjectId, "ref": "Rating" }],
"rating": { "type": Number }
});
var User = mongoose.model( "User", userSchema ),
Rating = mongoose.model( "Rating", ratingSchema ),
Bourbon = mongoose.model( "Bourbon", bourbonSchema );
mongoose.connect("mongodb://localhost/bourbon");
async.waterfall(
[
function(callback) {
async.each([User,Rating,Bourbon],function(model,callback) {
model.remove({},callback);
},
function(err) {
callback(err);
});
},
function(callback) {
Bourbon.create({
"name": 'test',
"blog": 'test',
"photo": 'test'
},callback);
},
function(bourbon,callback) {
Bourbon.create({
"name": 'another',
"blog": 'another',
"photo": 'another'
},callback);
},
function(bourbon,callback) {
User.create({ "name": 'ted' },function(err,user) {
if (err) callback(err);
Rating.create({
"bourbonId": bourbon,
"userId": user,
"rating": 5
},function(err,rating1) {
callback(err,user,bourbon,rating1)
});
});
},
function(user,bourbon,rating1,callback) {
Rating.create({
"bourbonId": bourbon,
"userId": user,
"rating": 7
},function(err,rating2) {
callback(err,bourbon,rating1,rating2);
});
},
function(bourbon,rating1,rating2,callback) {
Bourbon.findById(bourbon.id,function(err,bourbon) {
bourbon.ratings.push(rating1,rating2);
bourbon.save(function(err,bourbon) {
callback(err)
});
});
},
function(callback) {
async.series(
[
function(callback) {
Bourbon.find({},function(err,results) {
if (err) callback(err);
async.eachLimit(results,10,function(result,callback) {
var plain = result.toObject();
plain.bourbonId = plain._id.toString();
plain.avgRating = 0;
delete plain._id;
db.insert(plain,callback);
},callback);
});
},
function(callback) {
Rating.aggregate(
[
{ "$group": {
"_id": "$bourbonId",
"avgRating": { "$avg": "$rating" }
}}
],
function(err,results) {
if (err) callback(err);
async.eachLimit(results,10,function(result,callback) {
db.update(
{ "bourbonId": result._id.toString() },
{ "$set": { "avgRating": result.avgRating } },
callback
);
},callback);
}
);
}
],
function(err) {
if (err) callback(err);
db.find({},{ '_id': 0 },callback);
}
);
}
],
function(err,results) {
if (err) throw err;
console.log( results );
mongoose.disconnect();
}
);
Returns 结果符合预期:
[ { name: 'test',
blog: 'test',
photo: 'test',
__v: 0,
ratings: [],
bourbonId: '54c17bea8aa5f8c9161f5b6e',
avgRating: 0 },
{ name: 'another',
blog: 'another',
photo: 'another',
__v: 1,
ratings: [ [Object], [Object] ],
bourbonId: '54c17bea8aa5f8c9161f5b6f',
avgRating: 6 } ]