草庐IT

javascript - Mongoose 的行为和模式

coder 2023-05-05 原文

我目前正在与mongodb一起学习nodejs,有两件事使我有些困惑。

(1),
当使用新的模式和模型名称时(不在db中),该名称将更改为其复数形式。例子:

mongoose.model('person', personSchema);

在数据库中,该表将被称为“人物”。
这难道不容易使新开发人员感到困惑,为什么他们以这种方式实现它?

(2),
第二件事是,每当我想引用mongoDb中的现有模型时(假设在db中,存在一个名为people的表)。然后在我的nodejs代码中,我仍然必须定义一个Schema以便创建引用该表的模型。
personSchema = new mongoose.Schema({});
mongoose.model('person',personSchema);

不寻常的是,如何定义架构似乎无关紧要,它可以像上面一样为空,也可以使用随机属性填充,但是该模型将始终获得正确的表并且CRUD操作可以正常执行。

那么,除了定义用于创建新表的表结构之外,Schema的用途是什么?

非常感谢,

最佳答案

实际上,您通常最好问两个问题,以供将来引用。

1.多元化

简而言之,这是一个好习惯。更详细地说,这通常是合乎逻辑的,因为您所指的是项或对象的“集合”。因此,“集合”中的一般推论是“许多”,因此“对象”本身的名称具有复数形式。

因此,“人”集合意味着它实际上是由许多“人”对象组成的,就像“狗”到“狗”或“猫”到“猫”一样。不一定是“牛”到“牛”,但通常来讲 Mongoose 并不能真正处理多态实体,因此,除非有其他属性将其指定为“牛”,否则那里就不会有“牛”或“野牛”对象。

当然,如果您想使用以下两种形式之一并指定自己的名称,都可以更改此设置:

var personSchema = new Schema({ ... },{ "collection": "person" });

mongoose.model( "Person", personSchema, "person" );

但是,模型通常是“单数”模型名称,而“集合”是良好实践的复数形式(当存在许多情况时)。此外,我能想到的每个SQL数据库ORM都采用这种方式。因此,实际上,这只是遵循大多数人们已经习惯的做法。

2.为什么要使用模式?

MongoDB实际上是“无模式的”,因此它没有任何“模式”的内部概念,这与基于SQL的关系数据库有很大的不同,后者在“表”定义中保留了自己的“模式”定义。

尽管这实际上是MongoDB的“优势”,因为数据并不局限于特定的布局,但有些人实际上喜欢这种方式,或者通常希望封装控制数据存储方式的逻辑。

由于这些原因, Mongoose 支持定义“模式”的概念。这使您可以说出“绑定(bind)”到该集合(模型)中的“允许”哪些字段,以及可以包含哪些“类型”的数据。

您当然可以采用“无模式”方法,但是仍然必须定义与模型“绑定(bind)”的模式对象,而不必“严格”:
var personSchema = new Schema({ },{ "strict": false });
mongoose.model( "Person", personSchema );

然后,您几乎可以将任何所需内容添加为数据,而没有任何限制。

但是相反的情况是,人们“通常”确实希望强制执行某种类型的规则,例如哪些字段和什么类型。这意味着只能发生“定义的”事情:
var personSchema = new Schema({
    name: { type: String, required: true },
    age: Number,
    sex: { type: String, enum: ["M","F"] },
    children: [{ type: Schema.Types.ObjectId, ref: "Person" }],
    country: { type: String, default: "Australia" }
});

因此,这里的规则分解为:
  • “名称”中只能包含“字符串”数据。这里有一段JavaScript习惯用法,因为JavaScript中的所有内容实际上都会被字符串化。这里的另一件事是“必需的”,因此,如果在发送给.save()的对象中不存在此字段,它将抛出验证错误。
  • “年龄”必须是数字。如果尝试使用此字段中提供的数字以外的其他数据对对象进行.save()编码,则将引发验证错误。
  • “sex”必须再次为字符串,但是这次我们添加了“constraint”来表示有效值是什么。同样,如果您没有提供正确的数据,这也会引发验证错误。
  • “子级”实际上是项目的数组,但是这些只是指向另一个模型中不同项目的“引用” ObjectId值。或者在这种情况下就是这个。因此,当您添加到“子项”时,它将把该ObjectId引用保留在其中。当需要时, Mongoose 实际上可以稍后用其实际的“Person”对象对它们进行.populate()编码。这在MongoDB中模拟了一种“嵌入”形式,但是当您实际上要单独存储对象而不每次都“嵌入”时使用。
  • “country”仍然只是一个String,不需要任何特殊内容,但是如果没有其他显式提供的值,我们将为它提供一个默认值以进行填充。


  • 您还可以执行许多其他操作,建议您通过the documentation阅读。在那里对所有内容进行了详细的解释,如果您有特定的问题,则可以随时问“这里”(例如)。

    因此,MongoDB所做的事情与SQL数据库的工作方式有所不同,并且抛出了通常保存在“意见”中的某些事情,以便无论如何都可以在应用程序业务逻辑层更好地实现。

    因此,在Mongoose中,它试图“退回”人们喜欢使用传统关系数据库的一些好东西,并允许轻松编写一些规则和良好实践,而无需编写其他代码。

    还有一些逻辑可以帮助“模拟”(压力不够大)“联接”,因为有一些方法可以“帮助”您从其他来源检索“相关”数据,方法是提供一些定义,其中“数据驻留在“架构”定义中的“模型”。

    我是否还没有提到“模式”定义又只是对象并且可以重用?嗯,是的,它们实际上可以绑定(bind)到“许多”模型,这些模型可以或可以不驻留在同一数据库中。

    这里的一切功能和目的都比您目前所知道的要多得多,这里的好建议是继续学习。那是实现这一目标的通常途径。“哦,现在我明白了,这就是他们这样做的方式”。

    关于javascript - Mongoose 的行为和模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24668976/

    有关javascript - Mongoose 的行为和模式的更多相关文章

    1. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

      我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

    2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

      我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

    3. ruby - 如何在续集中重新加载表模式? - 2

      鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

    4. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

      我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

    5. ruby - 是否有用于序列化和反序列化各种格式的对象层次结构的模式? - 2

      给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最

    6. ruby - Ruby gsub 替换中的行为不一致? - 2

      两个gsub产生不同的结果。谁能解释一下为什么?代码也可在https://gist.github.com/franklsf95/6c0f8938f28706b5644d获得.ver=9999str="\tCFBundleDevelopmentRegion\n\ten\n\tCFBundleVersion\n\t0.1.190\n\tAppID\n\t000000000000000"putsstr.gsub/(CFBundleVersion\n\t.*\.).*()/,"#{$1}#{ver}#{$2}"puts'--------'putsstr.gsub/(CFBundleVersio

    7. ruby-on-rails - Ruby 中意外的大小写行为 - 2

      我在一段非常简单的代码(如我所想)中得到了一个错误的值:org=4caseorgwhenorg=4val='H'endputsval=>nil请不要生气,我希望我错过了一些非常明显的东西,但我真的想不通。谢谢。 最佳答案 这是典型的Ruby错误。case有两种被调用的方法,一种是你传递一个东西作为分支的基础,另一种是你不传递的东西。如果您确实在case中指定了一个表达式语句然后评估所有其他条件并与===进行比较.在这种情况下org评估为false和org===false显然不是真的。所有其他情况也是如此,它们要么是真的,要么是假的。

    8. ruby-on-rails - environment.rb 中设置的常量在开发模式中消失 - 2

      了解Rails缓存如何工作的人可以真正帮助我。这是嵌套在Rails::Initializer.runblock中的代码:config.after_initializedoSomeClass.const_set'SOME_CONST','SOME_VAL'end现在,如果我运行script/server并发出请求,一切都很好。然而,在我的Rails应用程序的第二个请求中,一切都因单元化常量错误而变得糟糕。在生产模式下,我可以成功发出第二个请求,这意味着常量仍然存在。我已通过将以上内容更改为以下内容来解决问题:config.after_initializedorequire'some_cl

    9. ruby - 使对象的行为类似于 ruby​​ 中并行分配的数组 - 2

      假设您在Ruby中执行此操作:ar=[1,2]x,y=ar然后,x==1和y==2。是否有一种方法可以在我自己的类中定义,从而产生相同的效果?例如rb=AllYourCode.newx,y=rb到目前为止,对于这样的赋值,我所能做的就是使x==rb和y=nil。Python有这样一个特性:>>>classFoo:...def__iter__(self):...returniter([1,2])...>>>x,y=Foo()>>>x1>>>y2 最佳答案 是的。定义#to_ary。这将使您的对象被视为要分配的数组。irb>o=Obje

    10. ruby-on-rails - 使用 javascript 更改数据方法不会更改 ajax 调用用户的什么方法? - 2

      我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的

    随机推荐