gpt4 book ai didi

node.js - 如何在 Mongoose /Node 中获得平均评分

转载 作者:可可西里 更新时间:2023-11-01 10:43:21 24 4
gpt4 key购买 nike

我在 angularjs 的前端有一个星级评级指令,我可以将评级保存到评级集合中。这是我的评级模式/模型:

var mongoose = require('mongoose');

module.exports = mongoose.model('Rating', {
bourbonId: {type: mongoose.Schema.ObjectId, ref: 'Bourbon'},
userId: {type: mongoose.Schema.ObjectId, ref: 'User'},
rating: {type: Number, required: true},
ratingId : {type: mongoose.Schema.ObjectId}

});

这是我需要平均评分的项目:

 'use strict';

var mongoose = require('mongoose'),
BourbonSchema = null;

module.exports = mongoose.model('Bourbon', {
BourbonId: {type: mongoose.Schema.ObjectId},
name: {type: String, required: true},
blog: {type: String, required: true},
photo: {type: String, required: true},
ratings: {type: mongoose.Schema.ObjectId, ref: 'Rating'},
rating: {type: Number}

});

var Bourbon = mongoose.model('Bourbon', BourbonSchema);
module.exports = Bourbon;

我需要找到一种通过 bourbon ID 进行匹配的方法。从堆栈溢出来看,似乎使用聚合函数可能是可行的方法。 stack overflow link

这是我 Controller 中的当前损坏代码。我知道它还有很长的路要走,以及我使用 async.map 尝试解决此问题的失败尝试:

    'use strict';

var Bourbon = require('../../../models/bourbon'),
Rating = require('../../../models/rating');
//async = require('async');

module.exports = {
description: 'Get Bourbons',
notes: 'Get Bourbons',
tags:['bourbons'],
handler: function(request, reply){
Bourbon.find(function(err, bourbons){
Bourbon.findOne(id, 'Rating', function(err, bourbon){
Rating.aggregate([
{$match: {bourbonId: {$in: bourbon.ratings}}},
{$group: {bourbonId: bourbon._id, average: {$avg: '$rating'}}}
], function(err, result){
bourbon.rating = result;
reply({bourbons:bourbons});
console.log('Bourbs', bourbons);
});
});
});
}
};

任何帮助将不胜感激。把我的头撞在砖墙上,现在只是扔出随机代码。 ..


这是我实现的:型号:

'use strict';

var mongoose = require('mongoose'),
BourbonResultSchema = null;


module.exports = mongoose.model('BourbonResult', {
_Id: {type: mongoose.Schema.ObjectId, 'ref': 'Bourbon'},
avgRating: {type: Number}

});


var BourbonResult = mongoose.model('BourbonResult', BourbonResultSchema, null);
module.exports = BourbonResult;

Controller :

  'use strict';

var Bourbon = require('../../../models/bourbon'),
Rating = require('../../../models/rating'),
BourbonResult = require('../../../models/bourbonResult');
//async = require('async');

module.exports = {
description: 'Get Bourbons',
notes: 'Get Bourbons',
tags:['bourbons'],
handler: function(request, reply){

Rating.aggregate(
[
{'$group':{
'_id': '$bourbonId',
'avgRating': {'$avg': '$rating'}
}}
],
function(err,bourbons){
// Map plain results to mongoose document objects
bourbons = bourbons.map(function(result){
return new BourbonResult(result);
});

Bourbon.populate(bourbons,{'path': '_id'},function(err,bourbons){
reply({bourbons:bourbons});
console.log('BourbsRESSSSSS', JSON.stringify(bourbons, undefined, 2));
});
}
);

}
};

这是我从控制台日志中得到的信息:

BourbsRESSSSSS [ { _id: 
{ _id: 54acf382894ee2bcdebbc7f5,
name: 'example2',
photo: 'http://aries-wineny.com/wp-content/uploads/2014/09/woodford-reserve.jpg',
blog: 'example2',
__v: 0 },
avgRating: 3.3333333333333335 },
{ _id:
{ _id: 54a77e0fe63c850000f1269c,
name: 'example',
photo: 'http://aries-wineny.com/wp-content/uploads/2014/09/woodford-reserve.jpg',
blog: 'example',
__v: 0 },
avgRating: 3 } ]

============================================= =========================

完美!

最佳答案

如果您要做的是在输出中列出针对每个“波旁威士忌”的“平均”评级,则可能有几种方法。但更简洁的方法之一是在表示聚合结果结构的特殊对象模型上使用 Mongoose 填充。

除了“bourbon”之外,您在这里似乎没有任何其他“类型”的“评分”,因此按理说您只想聚合整个集合。

// Set up a schema and model to match result structure
var bourbonResultSchema = new Schema({
"_id": { "type": Schema.Types.ObjectId, "ref": "Bourbon" },
"avgRating": Number
});

// The "null" for the collection is because there will not be any physical storage
var BourbonResult = mongoose.model( "BourbonResult", bourbonResultSchema, null );


// Aggregate an mapping code

Rating.aggregate(
[
{ "$group": {
"_id": "$bourbonId",
"avgRating": { "$avg": { "$ifNull": ["$rating",0 ] } }
}}
],
function(err,results) {
if (err) throw err;

// Map plain results to mongoose document objects
results = results.map(function(result) {
return new BourbonResult(result);
});

Bourbon.populate(results,{ "path": "_id" },function(err,results) {
if (err) throw err;
reply(results);
console.log( JSON.stringify( results, undefined, 2 ) );
})
}
);

因此,您定义了一个模式和模型,以匹配从聚合返回的结果的结构。这样做是为了让您稍后可以调用 .populate()

聚合返回的结果不是 Mongoose 文档,而是普通对象。然后,通过 .map() 方法将所有结果传递给 BourbonResult 对象,以返回 BourbonResult 数组。

由于这些不是 mongoose 文档,您可以调用 .populate() 的模型方法,该方法将 mongoose 文档数组作为第一个参数。第二个“选项”参数告诉方法用于填充的字段路径,即 _id 之前定义的引用 Bourbon 模型。

.populate() 的回调中,返回的结果合并了从聚合返回的平均分数和 _id 中的完整 Bourbon 对象> 领域。如果您真的愿意,您还可以对每个 Bourbon 对象运行进一步的 .populate() 语句,以获取它的任何引用。有点复杂但可能。

请注意,“Bourbon”模型中的“bourbonId”字段可能有点多余。 MongoDB 总是有一个唯一的 _id 字段,引用对象链接使用的实际值是该字段,除非另有说明。即使您需要像我为 BourbonResult 那样定义一个引用,您也可以这样做。


带有修改后的架构示例的完整列表:

var async = require('async'),
mongoose = require('mongoose'),
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 bourbonResultSchema = new Schema({
"_id": { "type": Schema.Types.ObjectId },
"avgRating": Number
});

var User = mongoose.model( "User", userSchema ),
Rating = mongoose.model( "Rating", ratingSchema ),
Bourbon = mongoose.model( "Bourbon", bourbonSchema ),
BourbonResult = mongoose.model(
"BourbonResult", bourbonResultSchema, null );


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) {
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) {
Rating.aggregate(
[
{ "$group": {
"_id": "$bourbonId",
"avgRating": { "$avg": { "$ifNull": ["$rating", 0 ] } }
}},
],
function(err,results) {
console.log(results);

results = results.map(function(result) {
return new BourbonResult(result);
});

Bourbon.populate(
results,
{ "path": "_id" },
function(err,results) {
console.log(results);
callback(err);
}
)

}
);
}
],
function(err) {
if (err) throw err;
mongoose.disconnect();
}
)

给出输出:

[ { _id: 54af7581efc755470845005c, avgRating: 6 } ]
[ { _id:
{ _id: 54af7581efc755470845005c,
name: 'test',
blog: 'test',
photo: 'test',
__v: 1,
ratings: [ 54af7581efc755470845005e, 54af7581efc755470845005f ] },
avgRating: 6 } ]

关于node.js - 如何在 Mongoose /Node 中获得平均评分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27853105/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com