如何从 Node.js / Express 应用程序的 Mongoose 预挂钩中查询?

Posted

技术标签:

【中文标题】如何从 Node.js / Express 应用程序的 Mongoose 预挂钩中查询?【英文标题】:How to query from within Mongoose pre hook in a Node.js / Express app? 【发布时间】:2013-10-17 09:09:36 【问题描述】:

我正在使用带有 Mongoose ORM 的 MongoDB 在 Node.js/Express 中构建一个基本博客。

我有一个预“保存”钩子,我想用它来为我自动生成博客/创意 slug。这工作得很好,除了在继续之前我想查询是否有任何其他现有帖子具有相同 slug 的部分。

但是,this 似乎无权访问 .find 或 .findOne(),因此我不断收到错误消息。

解决这个问题的最佳方法是什么?

  IdeaSchema.pre('save', function(next) 
    var idea = this;

    function generate_slug(text) 
      return text.toLowerCase().replace(/[^\w ]+/g,'').replace(/ +/g,'-').trim();
    ;

    idea.slug = generate_slug(idea.title);

    // this has no method 'find'
    this.findOne(slug: idea.slug, function(err, doc) 
      console.log(err);
      console.log(doc);
    );

    //console.log(idea);
    next();
  );

【问题讨论】:

【参考方案1】:

不幸的是,它没有很好地记录(在Document.js API docs 中没有提到它),但是文档可以通过constructor 字段访问他们的模型 - 我一直使用它来记录插件中的内容,这给出了我可以访问它们所连接的模型。

module.exports = function readonly(schema, options) 
    schema.pre('save', function(next) 
        console.log(this.constructor.modelName + " is running the pre-save hook.");

        // some other code here ...

        next();
    );
);

对于你的情况,你应该可以做到:

IdeaSchema.pre('save', function(next) 
    var idea = this;

    function generate_slug(text) 
        return text.toLowerCase().replace(/[^\w ]+/g,'').replace(/ +/g,'-').trim();
    ;

    idea.slug = generate_slug(idea.title);

    // this now works
    this.constructor.findOne(slug: idea.slug, function(err, doc) 
        console.log(err);
        console.log(doc);
        next(err, doc);
    );

    //console.log(idea);
);

【讨论】:

请注意,如果您要根据findOne() 的结果修改文档或抛出错误或其他内容,则需要将next() 回调移动到 findOne 中回调。 你到底是怎么学会的?这太棒了,应该明确记录下来...... 我们可以在 findOne 回调方法中使用 .save() 函数吗?我们可以在哪些查询中使用 .save() 函数? 这就是我有时依赖 *** 而不是文档的原因。有些文档太令人沮丧了。如果没有 ***,我怎么会知道这一点?【参考方案2】:

this 你得到的是文件,而不是模型。文档中不存在方法 findOne。

如果您需要模型,您可以随时检索它,如here 所示。但更聪明的做法是在创建时将模型分配给变量。 然后在任何你想要的地方使用这个变量。如果它在另一个文件中,则使用 module.exports 并要求在项目中的其他任何地方获取它。 像这样的:

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
mongoose.connect('mongodb://localhost/dbname', function (err) 
// if we failed to connect, abort
if (err) throw err;
var IdeaSchema = Schema(
    ...
);
var IdeaModel = mongoose.model('Idea', IdeaSchema);
IdeaSchema.pre('save', function(next) 
    var idea = this;

    function generate_slug(text) 
        return text.toLowerCase().replace(/[^\w ]+/g,'').replace(/ +/g,'-').trim();
    ;

    idea.slug = generate_slug(idea.title);

    // this has no method 'find'
    IdeaModel.findOne(slug: idea.slug, function(err, doc) 
        console.log(err);
        console.log(doc);
    );

    //console.log(idea);
    next();
   );
// we connected ok
)

【讨论】:

所以基本上,不要通过查询来在 pre-hook 中找到可能的重复项。在我 save() 之前做吗? 不,您可以随时在模型上调用查询方法。让我编辑我的答案以添加代码。

以上是关于如何从 Node.js / Express 应用程序的 Mongoose 预挂钩中查询?的主要内容,如果未能解决你的问题,请参考以下文章

node.js 与 express 如何从 url 中删除查询字符串

如何从部署在 AWS Elastic beanstalk 上的 node.js express 应用程序获取客户端 IP?

如何启用调试 express.js/node.js 应用程序

Node.js + express web应用如何打包部署?

如何使用 Express 和 Node.js 从表单发送参数

从 Express/node.js Web 应用程序预填充 HTML/Jade