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

cho*_*ovy 9 mongoose mongodb node.js

我有一个项目和用户的架构.我想允许用户喜欢或不喜欢某个项目,我还希望在项目和用户上存储评级关联.

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: [???]
});
Run Code Online (Sandbox Code Playgroud)

用户存储项目ref,并且该项目存储用户对于喜欢/不喜欢的参考.我不确定如何存储作为属性的评级,因为我想要用户和他们评价项目的价值.

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

我还想获得用户评级的项目列表以及评级值:

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

我的"评级"架构应该是什么样的?是否可以存储两个值?用户对象ID和评级值(整数)并具有这些的集合?

我用我的方法看到的另一个问题是mongoose还不支持深度填充,所以我必须使用一个模块(https://github.com/JoshuaGross/mongoose-subpopulate),这在很大程度上是un -tested或以不同的方式存储它,不会有多个嵌套级别,所以我可以用.populate()获取我的数据

感谢任何反馈,因为我是noSQL的新手,也许我对此过于复杂.

Oli*_*nde 6

我会像你说的那样做.我会使用评级架构:

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

如果您希望能够从User模式访问评级,则必须添加一个钩子,以便将任何已保存的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
});
Run Code Online (Sandbox Code Playgroud)

关于,"我用我的方法看到的另一个问题是mongoose还不支持深度填充",如果你不想使用mongoose-subpopulate hack,我建议你重构你的模型到静态方法的加载.例如:

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);
      }
    });
}
Run Code Online (Sandbox Code Playgroud)

编辑:既然我再次考虑它,为什么不简单地将评级存储为UserSchema中的嵌入文档?

var UserSchema = new Schema({
  /* ... */
  ratings: [ RatingSchema ]
});
Run Code Online (Sandbox Code Playgroud)

然后你可以这样填充:

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

    console.log(user.ratings);
  });
Run Code Online (Sandbox Code Playgroud)