mongoose如何管理参考文件中的计数

时间:2014-01-27 15:55:19

标签: node.js mongoose

所以我有这些架构:

'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
    Schema = mongoose.Schema;


/**
 * Comment Schema
 */
var CommentSchema = new Schema({
    post_id: {
        type: Schema.Types.ObjectId,
        ref: 'Post',
        required: true
    },
    author:{
        type: String,
        required: true
    },
    email:{
        type: String,
        required: true
    },
    body: {
        type: String,
        required: true,
        trim: true
    },
    status: {
        type: String,
        required: true,
        default: 'pending'
    },
    created: {
        type: Date,
        required: true,
        default: Date.now
    },
    meta: {
        votes: Number
    }
});

/**
 * Validations
 */
CommentSchema.path('author').validate(function(author) {
    return author.length;
}, 'Author cannot be empty');

CommentSchema.path('email').validate(function(email) {
    return email.length;
}, 'Email cannot be empty');

CommentSchema.path('email').validate(function(email) {
    var emailRegex = /^([\w-\.]+@([\w-]+\.)+[\w-]{2,4})?$/;
    return emailRegex.test(email);
}, 'The email is not a valid email');

CommentSchema.path('body').validate(function(body) {
    return body.length;
}, 'Body cannot be empty');

mongoose.model('Comment', CommentSchema);

'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
    monguurl = require('monguurl'),
    Schema = mongoose.Schema;


/**
 * Article Schema
 */
var PostSchema = new Schema({
    title: {
        type: String,
        required: true,
        trim: true
    },
    author:{
        type: String,
        required: true,
        default: 'whisher'
    },
    slug: {
        type: String,
        index: { unique: true }
    },
    body: {
        type: String,
        required: true,
        trim: true
    },
    status: {
        type: String,
        required: true,
        trim: true
    },
    created: {
        type: Date,
        required: true,
        default: Date.now
    },
    published: {
        type: Date,
        required: true
    },
    categories: {
        type: [String], 
        index: { unique: true }
    },
    tags: {
        type: [String], 
        required: true,
        index: true
    },
    comment: {
        type: Schema.Types.ObjectId, 
        ref: 'CommentSchema'
    },
    meta: {
        votes: Number
    }
});

/**
 * Validations
 */
PostSchema.path('title').validate(function(title) {
    return title.length;
}, 'Title cannot be empty');

PostSchema.path('body').validate(function(body) {
    return body.length;
}, 'Body cannot be empty');

PostSchema.path('status').validate(function(status) {
    return /publish|draft/.test(status);
}, 'Is not a valid status');

PostSchema.plugin(monguurl({
  source: 'title',
  target: 'slug'
}));

mongoose.model('Post', PostSchema);

通过api我查询帖子

exports.all = function(req, res) {
    Post.find().sort('-created').exec(function(err, posts) {
        if (err) {
           res.jsonp(500,{ error: err.message });
        } else {
            res.jsonp(200,posts);
        }
    });
};

如何检索帖子中有多少条评论? 我的意思是我希望在post对象中有一个额外的适当性 比如post.ncomments。

我想到的第一件事就是增加额外的东西 字段到post架构并在用户时更新它 添加评论

meta: {
    votes: Number,
    ncomments:Number
}

但我认为这似乎很难看

2 个答案:

答案 0 :(得分:2)

看起来您的Post架构只允许发表一条评论:

// ....
comment: {
    type: Schema.Types.ObjectId, 
    ref: 'CommentSchema'
},
// ....

一个考虑因素是将您的评论作为子文档存储在您的帖子而不是他们自己的集合中。一般来说,您是否只会因为与相关帖子相关的问题来查询您的评论,或者您是否会经常查看与其帖子无关的所有评论?

如果将注释移动到子文档,那么您将能够执行post.comments.length之类的操作。

但是,如果将注释保留为单独的集合(NoSQL DB中的关系结构 - 有时会有理由这样做),则没有自动执行此操作的方法。 Mongo无法进行连接,因此您必须发出第二个查询。你有几个方法可以做到这一点。一个是post实例上的实例方法。您也可以手动CommentSchema.count({postId: <>})

您提出的解决方案也非常有效。该策略用于可以进行连接的关系数据库,因为它比每次计算所有注释都有更好的性能。

答案 1 :(得分:2)

如果您希望这可能是最有效的解决方案,那么手动将number_comments这样的字段添加到Post架构可能是最好的方法,特别是如果您想要执行诸如操作之类的操作多个帖子(比如基于评论的排序)。即使您使用索引进行计数,它也不可能像计算预先计算的那样有效(并且最终,如果您已经预先计算了,您可以执行更多类型的查询选择嵌入评论。

var PostSchema = new Schema({
    /* others */
    number_comments: {
        type: Number
    } 
});

更新号码:

Post.update({ _id : myPostId}, {$inc: {number_comments: 1}}, /* callback */);

此外,comment中不需要PostSchema字段,除非您将其用作“最新”样式字段(或者只有一个字段只有一个)。您在Post架构中拥有Comment引用这一事实足以找到给定Comment的所有Post

Comments.find().where("post_id", myPostId).exec(/* callback */);

您需要确保该字段已编入索引。由于您为字段指定了populate,因此可以使用ref,您可以考虑将字段重命名为"post"

Comments.find().where("post", myPostId).exec(/* callback */);

您仍然只将post字段设置为_id的{​​{1}}(而不是实际的Post对象实例)。

您也可以选择在Post中嵌入评论。 MongoDB网站上有一些关于这些选择的good information。请注意,即使您嵌入了注释,也需要恢复整个数组才能获得计数。