处理mongoose上的模式引用

时间:2015-04-11 23:45:20

标签: node.js asynchronous mongoose foreign-keys

我正在尝试使用Node.js,mongoose和restify定义一个简单的RESTful API。目标是让用户可以评论其他用户的个人资料。为此我有一个注释端点,它接收文本,作者和评论的目标(其他用户)。

我想引用用户,所以我定义了下一个模式:

用户架构:

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var UserSchema = new Schema({
  "username": { type: String, unique: true, required: true },
  "password": { type: String, required: true },
  "comments": [{ type: Schema.Types.ObjectId, ref: 'Comment' }]
});

mongoose.model('User', UserSchema);

评论架构:

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var CommentSchema = new Schema({
  date: { type: Date, default: Date.now },
  text: { type: String, required: true },
  author: { type: mongoose.Schema.Types.ObjectId, ref: "User", required: true },
  target: { type: mongoose.Schema.Types.ObjectId, ref: "User", required: true }
});

mongoose.model('Comment', CommentSchema);

我也有这个控制器(只显示createComment函数):

exports.createComment = function(req, res, next) {
  var authorId, targetId;

  User.findOne({ _id: req.params.authorId}, function(err, author) {
    if (author) {
      User.findOne({ _id: req.params.targetId}, function(err, target) {
        if (target) {
          var comment = new Comment();
          comment.text = req.params.text;
          comment.author = author._id;
          comment.target = target._id;

          comment.save(function(err, comment) {
            if (err) {
              res.status(500);
              res.json({
                type: false,
                data: 'Error occurred: ' + err
              });
            } else {
              res.json({
                type: true,
                data: comment
              });
            }
          });
        } else {
          res.json({
            type: false,
            data: 'User ' + req.params.authorId + ' not found'
          });
        }
      });
    } else {
      res.json({
        type: false,
        data: 'User ' + req.params.targetId + ' not found'
      });
    }
  });
};

所以,我有三个问题:

  • 为什么我需要检查用户是否存在?我想只收到id并存储它,但我还要再做两个查询来自己查看。
  • 我需要做什么来存储用户只有那个用户是目标的评论? 在已修改的代码中解决
  • 如何简化此代码?按顺序执行异步查询是一件痛苦的事。我希望有一般性错误而不必处理每一个错误。

编辑:我使用架构上的验证简化了代码:

评论架构:

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var User = mongoose.model('User');

var CommentSchema = new Schema({
  date: { type: Date, default: Date.now },
  text: { type: String, required: true },
  author: { type: Schema.Types.ObjectId, ref: "User", required: true },
  target: { type: Schema.Types.ObjectId, ref: "User", required: true }
});

CommentSchema.path('author').validate(function(value, respond) {
  User.findOne({ _id: value}, function(err, user) {
    respond(!err && user);
  });
}, 'Author doesn\'t exists');

CommentSchema.path('target').validate(function(value, respond) {
  User.findOne({ _id: value}, function(err, user) {
    respond(!err && user);
  });
}, 'Target user doesn\'t exists');

mongoose.model('Comment', CommentSchema);

控制器:

exports.createComment = function(req, res, next) {
  var comment = new Comment(req.body);

  comment.save(function(err, comment) {
    if (err) {
      res.status(500);
      res.json({
        type: false,
        data: 'Error occurred: ' + err
      });
    } else {
      User.findOne({ _id: comment.target }, function(err, user) {
        user.comments.push(comment);
        user.save();
      });

      res.json({
        type: true,
        data: comment
      });
    }
  });
};

这个问题是现在我必须在查询上使用_id(我想使用自定义ID),每次我想要保存评论时我都会做三个查询(2个用于验证,另外一个用于存储评论)。有更好的方法吗?

1 个答案:

答案 0 :(得分:0)

  1. 您可以在mongo中使用查询的select选项来仅选择用户的_id字段,如下所示:

    User.findOne({_id:req.params.authorId}).select({_id:1}).exec(function(err,user) {})

  2. 从mongo中提取userTarget后,需要将comment._id添加到他的评论列表中,并保存他:
    target.comments.push(comment._id); target.save(function(err, targetAfterSaved) {})

  3. 阅读asyncq,它们是我最喜欢的处理异步函数的库。对于具有您想要的错误的句柄,您可以添加一些侦听器 - here是来自restify站点的文档。

  4. 希望您理解,如果您需要任何帮助,请告诉我