我应该如何使用node.js在mongoose / mongdb中存储喜欢/不喜欢和评分

我有一个项目和用户的架构。 我想让用户喜欢或不喜欢一个项目,我也想存储一个评价协会的项目以及用户。

var UserSchema = new Schema({ username : { type: String, required: true, index: { unique: true } , likes : [{ type: Schema.ObjectId, ref: 'Item'}] , dislikes : [{ type: Schema.ObjectId, ref: 'Item'}] , ratings: [???] }); var ItemSchema = new Schema({ name: { type: String}, , likes : [{ type: Schema.ObjectId, ref: 'User'}] , dislikes : [{ type: Schema.ObjectId, ref: 'User'}] , ratings: [???] }); 

用户存储一个项目ref,该项目存储一个用户ref喜欢/不喜欢。 我不知道如何将评分作为属性存储,因为我希望用户和他们评价项目的价值。

 item.ratings.forEach(function(rating){ <%= rating.user.username %> gave <%= item.name %> a <%= rating.value %>. }); 

我也想得到一个用户已经评价的评价值的项目列表:

 user.ratings.forEach(function(rating){ <%= user.username %> has rated <%= rating.item.name %> and gave it a <%= rating.value %> }); 

我的“评级”模式应该是什么样子? 可以存储两个值吗? 一个用户对象的id和一个评价值(整数),并有这些的集合?

我用我的方法看到的另一个问题是,mongoose不支持深填充,所以我将不得不使用一个模块(https://github.com/JoshuaGross/mongoose-subpopulate),这主要是联合国 – testing或存储它不会有超过一个嵌套级别的方式,所以我可以用.populate()获得我的数据。

任何反馈是赞赏,因为我是新来的noSQL,也许我太过于复杂。

我会照你所说的去做。 我会使用评级模式:

 var RatingSchema = new Schema({ , _user : { type: ObjectId, ref: 'User' } , _item : { type: ObjectId, ref: 'Item' } , value : Integer }); 

如果您希望能够从用户模式访问评级,则必须添加一个挂钩,以便将所有保存的RatingSchema添加到user.ratings。

 var UserSchema = new Schema({ /* ... */ ratings: [{ type: Schema.ObjectId, ref: 'Rating'}] }); RatingSchema.post('save', function () { // push this.id to this._user.ratings // save this._user }); 

关于“我用我的方法看到的另外一个问题是mongoose不支持深度填充”,如果你不想使用mongoose亚群黑客,我build议你重新加载模型到静态方法。 例如:

 UserSchema.statics.findByIdAndDeepPopulate = function (i, cb) { UserSchema.findOne(id) .exec(function(err, user) { if (err || !user) return cb(new Error('User not found')); if (user._ratings.length == 0) return cb(null, user); // Load and populate every ratings in user._ratings for(var i = 0; i < user._ratings.length; i++) { function(i) { RatingSchema .populate('_item') .exec(err, function(rating) { user._ratings[i] = rating; if (i == user._ratings.length) return cb(null, user); }); }(i); } }); } 

编辑:现在我再次考虑它,为什么不简单地将评级作为embedded文档存储在UserSchema?

 var UserSchema = new Schema({ /* ... */ ratings: [ RatingSchema ] }); 

那么你可以简单地填充这种方式:

 UserSchema.findOne(id) .populate('ratings._item') .exec(function(err, user) { if (err || !user) return next(new Error('User not found')); console.log(user.ratings); }); 

您希望避免双重交叉连接,因为这意味着需要维护两次,而且由于Mongo不支持事务处理,当您希望连接数据双重连接时,它可能会创build半连接数据。 这就是说我重新思考你的模式是这样的:

 var like = { itemid: { type: Schema.ObjectId, ref: 'Item'} , rating: Number }; var UserSchema = new Schema({ username : { type: String, required: true, index: { unique: true } , likes : [like] , dislikes : [like] }); UserSchema.index({ 'likes.itemid': 1 }); UserSchema.index({ 'dislikes.itemid': 1 }); var User = db.model('User', UserSchema); var ItemSchema = new Schema({ name: String }); var Item = db.model('Item', ItemSchema); 

你可以添加喜欢或不喜欢说:

 var piano = new Item({name: 'Mason & Hamlin Baby Grand Piano' }); var Joe = new User({ username: 'Joe_Smith' }); Joe.likes.push({ itemid: piano._id, rating: 10 }); 

而当你想查找一个项目的喜欢:

 User.find({ 'likes.itemid': piano._id }, function(err, userLikes) { ... }); 

如果没有一个感觉适合你,那么你可以创build第三个集合…

 var UserSchema = new Schema({ username : { type: String, required: true, index: { unique: true } }); var User = db.model('User', UserSchema); var ItemSchema = new Schema({ name: String }); var Item = db.model('Item', ItemSchema); var LikesSchema = new Schema({ , userid: { type: Schema.ObjectId, ref: 'User'} , itemid: { type: Schema.ObjectId, ref: 'Item'} , rating: Number }); LikesSchema.index({ userid: 1, itemid: 1 }, { unique: true }); 

在这种情况下,规则可能是最容易做出正面评价是类似的,负面评价是不喜欢的。