Sequelize:你可以使用钩子为查询添加评论吗?

Posted

技术标签:

【中文标题】Sequelize:你可以使用钩子为查询添加评论吗?【英文标题】:Sequelize: can you use hooks to add a comment to a query? 【发布时间】:2016-12-09 23:04:00 【问题描述】:

Heroku recently posted a list of some good tips for postgres。 Track the Source of Your Queries 部分让我最感兴趣。我很好奇这是否可以与 Sequelize 一起使用。 I know that sequelize has hooks,但不确定是否可以使用挂钩来进行实际的查询字符串调整。

我很好奇是否可以使用钩子或其他 Sequelize 方法将注释附加到 Sequelize 查询(不使用 .raw)以跟踪查询的调用位置。

(附加和前置查询也将是helpful for implementing row-level security,特别是set role / reset role

编辑:是否可以为此使用sequelize.fn()

【问题讨论】:

【参考方案1】:

如果您只想在 SQL 查询中插入一个“标签”,您可以使用Sequelize.literal() 将文字字符串传递给查询生成器。将此添加到 options.attributes.include 将添加它,但是它还需要一个别名,因此您还必须传递某种值。

 Model.findById(id, 
   attributes: 
     include: [
       [Sequelize.literal('/* your comment */ 1'), 'an_alias'],
     ],
   ,
 );

这会产生类似于

的SQL
SELECT `model`.`id`, /* your comment */ 1 as `an_alias`
FROM `model` as `model`
WHERE `model`.`id` = ???

我尝试了一点自动化,它可能超出了这个答案的范围,但是您可以在使用 new Sequelize() 创建连接之前修改 Sequelize.Model.prototype 以调整方法的处理。您需要对所有要“标记”的方法执行此操作。

 // alias findById() so we can call it once we fiddle with the input
 Sequelize.Model.prototype.findById_untagged = Sequelize.Model.prototype.findById;

 // override the findbyId() method so we can intercept the options.
 Sequelize.Model.prototype.findById = function findById(id, options) 
   // get the caller somehow (I was having trouble accessing the call stack properly)
   const caller = ???;

   // you need to make sure it's defined and you aren't overriding settings, etc
   options.attributes.include.push([Sequelize.literal('/* your comment */ 1'), 'an_alias']);

   // pass it off to the aliased method to continue as normal
   return this.findById_untagged(id, options);
 

 // create the connection
 const connection = new Sequelize(...);

注意:可能无法自动执行此操作,因为 Sequelize 具有 use strict,因此无法访问 arguments.callerarguments.callee 属性。

第二个注意事项:如果您不关心修改 Sequelize.Model 原型,您还可以抽象您对 Sequelize 方法的调用并在那里调整选项。

function Wrapper(model) 
  return 
    findById(id, options) 
      // do your stuff
      return model.findById(id, options);
    ,
  ;


Wrapper(Model).findById(id, options);

第三条注意:您还可以提交拉取请求以将此功能添加到Sequelize 下的新选项值下,例如在查询末尾添加的options.comment

【讨论】:

感谢您提供全面而深思熟虑的答案。我印象非常深刻。也许对于调用者来说,如果从堆栈中选择正确的行,像try throw new Error(); catch ( error ) console.log( error.stack ); 这样的黑客可能会起作用,但会很慢;)

以上是关于Sequelize:你可以使用钩子为查询添加评论吗?的主要内容,如果未能解决你的问题,请参考以下文章

快递js + Sequelize和钩子

我可以在 Sequelize.js 中的单个查询中获取 ID 为 1 的类别和该类别的所有子类别吗?

Sequelize查询执行顺序错误

在运行 sequelize 迁移时如何打印原始查询?

Sequelize beforeConnect 钩子与 sequelize-typescript 未运行

Sequelize - 我必须在模型和查询中都指定“as”吗?