Mongoose“静态”方法与“实例”方法
Posted
技术标签:
【中文标题】Mongoose“静态”方法与“实例”方法【英文标题】:Mongoose 'static' methods vs. 'instance' methods 【发布时间】:2015-06-22 06:09:13 【问题描述】:我相信这个问题类似于this one,但术语不同。来自猫鼬4documentation:
我们也可以定义自己的自定义文档实例方法。
// define a schema
var animalSchema = new Schema( name: String, type: String );
// assign a function to the "methods" object of our animalSchema
animalSchema.methods.findSimilarTypes = function (cb)
return this.model('Animal').find( type: this.type , cb);
现在我们所有的动物实例都有一个可用的 findSimilarTypes 方法。
然后:
向模型添加静态方法也很简单。继续我们的animalSchema:
// assign a function to the "statics" object of our animalSchema
animalSchema.statics.findByName = function (name, cb)
return this.find( name: new RegExp(name, 'i') , cb);
var Animal = mongoose.model('Animal', animalSchema);
Animal.findByName('fido', function (err, animals)
console.log(animals);
);
似乎使用静态方法,每个动物实例也可以使用findByName
方法。 Schema 中的 statics
和 methods
对象是什么?有什么区别?为什么我要使用其中一个?
【问题讨论】:
【参考方案1】:statics
是模型上定义的方法。 methods
在文档(实例)上定义。
您可以使用 static 方法,例如 Animal.findByName
:
const fido = await Animal.findByName('fido');
// fido => name: 'fido', type: 'dog'
您可能会使用实例方法,例如fido.findSimilarTypes
:
const dogs = await fido.findSimilarTypes();
// dogs => [ name:'fido',type:'dog , name:'sheeba',type:'dog' ]
但你不会这样做 Animals.findSimilarTypes()
因为 Animals 是一个模型,它没有“类型”。 findSimilarTypes
需要一个 this.type
,它在 Animals 模型中不存在,只有一个文档实例会包含该属性,如模型中定义的那样。
同样,您不会¹做fido.findByName
,因为findByName
需要搜索所有文档,而fido
只是一个文档。
¹嗯,从技术上讲,您可以,因为实例确实可以访问集合(this.constructor
或 this.model('Animal')
),但拥有一个(至少在这种情况下)没有意义不使用实例中的任何属性的实例方法。 (感谢@AaronDufour 指出这一点)
【讨论】:
@laggingreflex 您的第二条评论不正确。您可以拥有fido.findByName
,因为fido
确实可以访问整个集合(通过this.model('Animal')
)。但是,拥有一个不使用实例中任何属性的实例方法并没有多大意义。
@lagginreflex 您是否在 mongoosejs.com 上编写了使用实际单词 static
获取免费堆栈点的文档?大声笑它实际上以@Startec 的方式展示了示例,使用Animal.statics.methodName
,但随后你出现了,作为我迄今为止在这方面找到的少数资源之一,并且说,基本上不要使用statics
这个词,例如Animals.methodName
,但在它显示的文档上。谢谢你,我怀疑这一点。【参考方案2】:
数据库逻辑应该封装在数据模型中。 Mongoose 提供了两种方法,方法和静态。 Methods 向文档添加实例方法,而 Statics 向模型本身添加静态“类”方法。 static 关键字定义模型的静态方法。不会在模型的实例上调用静态方法。相反,它们是在模型本身上调用的。这些通常是实用函数,例如创建或克隆对象的函数。像下面的例子:
const bookSchema = mongoose.Schema(
title:
type : String,
required : [true, 'Book name required']
,
publisher :
type : String,
required : [true, 'Publisher name required']
,
thumbnail :
type : String
type :
type : String
,
hasAward :
type : Boolean
);
//method
bookSchema.methods.findByType = function (callback)
return this.model('Book').find( type: this.type , callback);
;
// statics
bookSchema.statics.findBooksWithAward = function (callback)
Book.find( hasAward: true , callback);
;
const Book = mongoose.model('Book', bookSchema);
export default Book;
更多信息:https://osmangoni.info/posts/separating-methods-schema-statics-mongoose/
【讨论】:
【参考方案3】:对我来说,这并不意味着通过在“静态”或什至在“实例”关键字前面添加 Mongoose 来添加任何内容。
我相信静态的含义和目的在任何地方都是相同的,即使对于外星语言或某种代表模型的驱动程序也是如此,用于像另一种面向对象编程一样构建块。例如也一样。
来自***: 面向对象编程 (OOP) 中的方法是与消息和对象相关联的过程。对象由数据和行为组成。数据和行为构成一个接口,该接口指定对象的各种消费者[1] 中的任何一个如何使用该对象。
数据表示为对象的属性,行为表示为对象的方法。例如,一个 Window 对象可以具有诸如 open 和 close 之类的方法,而它的状态(在任何给定时间点是打开还是关闭)将是一个属性。
静态方法旨在与类的所有实例相关,而不是与任何特定实例相关。从这个意义上说,它们类似于静态变量。一个例子是一个静态方法,用于对类的每个实例的所有变量的值求和。例如,如果有一个 Product 类,它可能有一个静态方法来计算所有产品的平均价格。
Math.max(双a, 双b)
此静态方法没有拥有对象,并且不在实例上运行。它从其参数中接收所有信息。[7]
即使类的实例尚不存在,也可以调用静态方法。静态方法被称为“静态”,因为它们是在编译时根据调用它们的类来解析的,而不是像实例方法那样动态解析,实例方法是根据对象的运行时类型以多态方式解析的。
https://en.wikipedia.org/wiki/Method_(computer_programming)
【讨论】:
【参考方案4】:正如大家所说的,当我们想要对单个文档进行操作时使用方法,而当我们想要对整个集合进行操作时使用静态。但是为什么呢?
假设我们有一个架构:
var AnimalSchema = new Schema(
name: String,
type: String
);
现在如文档中所述,如果您需要检查数据库中特定文档的相似类型 你可以这样做:
AnimalSchema.methods.findSimilarType = function findSimilarType (cb)
return this.model('Animal').find( type: this.type , cb);
;
现在,这里的 this 指的是文档本身。所以,这意味着,这个文件 不知道它属于哪个模型,因为 methods 默认与模型无关,它只针对那个特定的文档 obj。 但是我们可以使用 this.model('anyModelName') 使其与模型一起工作。
现在我们为什么在寻找相似类型动物的情况下使用方法?
为了找到相似类型的动物,我们必须拥有一个动物对象,我们可以找到相似类型的动物。 我们拥有的那个动物对象让我们说: const Lion = await new Animal(name: Lion, type:"dangerous"); 接下来,当我们首先找到需要 Lion obj 的相似类型时,我们必须拥有它。 很简单,每当我们需要特定 obj/document 的帮助来做某事时,我们都会使用方法。
现在这里碰巧我们还需要整个模型来搜索更苗条的类型, 虽然它不能直接在方法中使用(记住 this.modelName 将返回 undefined)。我们可以通过将 this.model() 设置为我们的首选模型来获得它,在本例中为 Animal。 这就是方法的全部内容。
现在,statics 可以使用整个模型。 1)假设您要计算您将使用静态的所有动物的总 价格(假设模型具有价格字段)[因为您不需要任何特定的 Animal obj,所以我们不会使用方法] 2)你想找到有黄色皮肤的动物(假设模型有一个皮肤场),你会使用静力学。 [因为我们不需要任何特定的 Animal obj,所以我们不会使用方法]
例如:
AnimalSchema.statics.findYellowSkin = function findSimilarType (cb)
return this.find( skin: "yellow" , cb);
;
请记住,在 this 方法中引用模型,因此,this.modelName 将返回 Animal(在我们的例子中)。
但是就像方法一样,这里我们也可以(但我们不需要)设置模型使用。
AnimalSchema.methods.findSimilarType = function findSimilarType (cb)
return this.model('Animal').find( skin: "yellow" , cb); //just like in methods
;
所以你可以看到静态和方法都非常相似。
每当您有文档并且需要处理该文档时, 使用方法。每当您需要对整体做某事时 模型/集合,使用静态。
【讨论】:
【参考方案5】: 将.statics
用于static
方法。
将.methods
用于instance
方法。
//instance method
bookSchema.methods.findByType = function (callback)
return this.model('Book').find( type: this.type , callback);
;
// static method
bookSchema.statics.findBooksWithAward = function (callback)
Book.find( hasAward: true , callback);
;
【讨论】:
【参考方案6】:statics
与 methods
几乎相同,但允许定义直接存在于模型上的函数。
statics
属于 Model,methods
属于 Instance
【讨论】:
【参考方案7】:Static methods
适用于定义它们的整个模型,而instance methods
仅适用于集合中的特定文档。
this
在静态方法上下文中返回整个模型,而this
在实例方法上下文中返回文档。
比如说:
const pokemon = new mongoose.Schema()
pokemon.statics.getAllWithType = function(type)
// Query the entire model and look for pokemon
// with the same type
// this.find(type : type)
pokemon.methods.sayName = function()
// Say the name of a specific pokemon
// console.log(this.name)
const pokemonModel = mongoose.model('schema', pokemon)
const squirtle = new pokemonModel(name : "squirtle")
// Get all water type pokemon from the model [static method]
pokemonModel.getAllWithType("water")
// Make squirtle say its name [instance method]
squirtle.sayName()
【讨论】:
以上是关于Mongoose“静态”方法与“实例”方法的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Mongoose 中编写一个获取所有文档的静态方法?
Egg中使用egg-mongoose和常用的Mongoose 方法
Egg中使用egg-mongoose和常用的Mongoose 方法