Scopes-Scope本系列文章的应用示例已发布在GitHub上:sequelize-docs-Zh-CN。您可以Fork以帮助改进或Star以关注更新。欢迎星。范围允许您定义经常使用的查询以便以后使用。范围可以包括与常规查找器相同的所有属性where、include、limit等。定义范围在模型定义中定义,可以是查找器对象或返回查找器对象的函数。除了默认作用域,作用域只能是一个对象:constProject=sequelize.define('project',{//property},{defaultScope:{where:{active:true}},scopes:{deleted:{其中:{deleted:true}},activeUsers:{include:[{model:User,where:{active:true}}]},random:function(){return{where:{someNumber:Math.random()}}},accessLevel:function(value){return{where:{accessLevel:{[Op.gte]:value}}}}}});通过调用addScope定义模型后,您还可以添加作用域。这对于包含包含的范围特别有用,其中包含的模型可能在定义其他模型时未定义。始终应用默认范围。这意味着,使用上面的模型定义,Project.findAll()将创建以下查询:SELECT*FROMprojectsWHEREactive=true可以通过调用.unscoped()、.scope(null)或调用另一个范围来删除默认范围:Project.scope('deleted').findAll();//删除默认作用域SELECT*FROMprojectsWHEREdeleted=true也可以在作用域定义中包含作用域模型。这使您可以避免重复包含、属性或位置定义。使用上面的示例,并在包含的用户模型上调用活动范围(而不是直接在该包含对象中指定条件):activeUsers:{include:[{model:User.scope('active')}]}使用范围是通过在模型定义上调用.scope来应用,传递一个或多个范围的名称。.scope返回一个功能齐全的模型实例,它具有所有常用方法:.findAll、.update、.count、.destroy等。您可以保存此模型实例并稍后再次使用它:constDeletedProjects=Project.scope('删除');DeletedProjects.findAll();//过一会儿//让我们再次查找已删除的项目!DeletedProjects.findAll();作用域适用于.find、.findAll、.count、.update和.destroy。可以通过两种方式调用作为函数的作用域。如果作用域没有任何参数,则可以正常调用。如果范围采用参数,则传递一个对象:Project.scope('random',{method:['accessLevel',19]}).findAll();SELECT*FROMprojectsWHEREsomeNumber=42ANDaccessLevel>=19merge通过将范围数组传递给.scope或将范围作为连续参数传递,可以同时应用多个范围。//这两个是等价的.userId=users.idANDusers.active=true如果要应用其他范围以及默认范围,请将键defaultScope传递给.scope:Project.scope('defaultScope','deleted').findAll();SELECT*FROMprojectsWHEREactive=trueANDdeleted=true当调用多个范围时,来自后续范围的键将覆盖以前的范围(类似于_.assign)。考虑两个范围:{scope1:{where:{firstName:'bob',age:{[Op.gt]:20}},limit:2},scope2:{where:{age:{[Op.gt]:30}},limit:10}}调用.scope('scope1','scope2')将生成以下查询WHEREfirstName='bob'ANDage>30LIMIT10请注意,scope2覆盖限制和年龄,同时保留firstName.limit、offset、order、paranoid、lock和raw被覆盖,而where和include被浅合并。这意味着在同一模型和后续包含中具有相同键的对象将全部相互覆盖。当将查找对象直接传递给范围模型上的findAll时,同样的合并逻辑适用:Project.scope('deleted').findAll({where:{firstName:'john'}})WHEREdeleted=trueANDfirstName='john'删除的范围与查找器合并的位置。如果我们将where:{firstName:'john',deleted:false}传递给finder,删除的范围将被覆盖。关联Sequelize与关联有两个不同但相关的范围概念。区别很细微但很重要:关联作用域允许您在获取和设置关联时指定默认属性——这在实现多态关联时很有用。使用get、set、add和createassociatedmodel函数时,仅在两个模型之间的关联上调用此范围协会。这些范围适用于模型的常规查找和通过关联进行的查找。例如,考虑模型Post和Comment。评论与其他几个模型(图片、视频等)相关联,评论与其他模型的关联是多态的,这意味着除了外键commentable_id之外,评论还存储了一个可评论的列。可以使用关联范围实现多态关联:this.Post.hasMany(this.Comment,{foreignKey:'commentable_id',scope:{commentable:'post'}});当调用post.getComments()时,这将自动添加WHEREcommentable='post'。类似地,当新评论添加到帖子时,commentable会自动设置为“post”。关联的作用域意味着存在于后台,没有程序员需要担心它——它不能被禁用。有关多态性的更完整示例,请参阅关联范围然后考虑Post的默认范围仅显示活动帖子:where:{active:true}。该范围存在于关联模型(Post)中,而不是像可注释范围那样存在于关联中。就像在调用Post.findAll()时应用默认范围一样,它也会在调用User.getPosts()时应用-这只会返回该用户的活动帖子。要禁用默认范围,请将scope:null传递给getter:User.getPosts({scope:null})。同样,如果您想应用其他范围,请这样做:User.getPosts({scope:['scope1','scope2']});传递给协会。考虑一个获取用户所有已删除帖子的快捷方式:constPost=sequelize.define('post',attributes,{defaultScope:{where:{active:true}},scopes:{deleted:{where:{deleted:true}}}});User.hasMany(Post);//常规getPosts关联User.hasMany(Post.scope('deleted'),{as:'deletedPosts'});User.getPosts();//WHEREactive=trueUser.getDeletedPosts();//WHEREdeleted=true如果本文对您有帮助,请在下方点赞或starGitHub:sequelize-docs-Zh-CN支持,谢谢。
