Mongoose行为和架构

Mik*_*eNQ 6 javascript mongoose mongodb database-schema node.js

我目前正在和mongodb一起学习nodejs,有两件事让我感到困惑.

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

mongoose.model('person', personSchema);
Run Code Online (Sandbox Code Playgroud)

在数据库中,该表将被称为"人".是不是很容易混淆新开发人员,为什么他们这样实现呢?

(2),第二件事是每当我想引用mongoDb中的现有模型时(假设在db中,存在一个名为people的表).然后在我的nodejs代码中,我仍然需要定义一个Schema,以便创建一个引用该表的模型.

personSchema = new mongoose.Schema({});
mongoose.model('person',personSchema);
Run Code Online (Sandbox Code Playgroud)

不同寻常的是,我似乎无法定义架构,它可以像上面一样空,或填充随机属性,但模型将始终获得正确的表并且CRUD操作正常执行.

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

非常感谢,

Nei*_*unn 12

实际上有两个问题,你通常会更好地问一个问题,仅供将来参考.

1.多元化

简短形式是这是一种很好的做法.更详细地说,这通常是合乎逻辑的,因为您所指的是项目或对象的"集合".因此,"集合"中的一般推论是"很多",因此是"对象"本身被命名的复数形式.

因此,"人物"系列暗示它实际上由许多"人"物体组成,就像"狗"到"狗"或"猫"到"猫"一样.不一定是"bovines"到"cow",但一般来说mongoose并不真正处理多态实体,因此除非其他一些属性指定为"cow",否则不会有"bull"或"bison"对象.

如果您想要这些表单中的任何一个并指定自己的名称,您当然可以更改此项:

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

mongoose.model( "Person", personSchema, "person" );
Run Code Online (Sandbox Code Playgroud)

但是模型通常是"单数"模型名称,而"集合"是许多时候的复数形式的良好实践.此外,我能想到的每个SQL数据库ORM也都是这样做的.所以,这只是遵循大多数人已经习惯的做法.

2.为什么是Schema?

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

虽然这通常是MongoDB的"优势",因为数据并不依赖于某种布局,但有些人实际上喜欢它,或者通常希望以其他方式封装管理数据存储方式的逻辑.

出于这些原因,mongoose支持定义"Schema"的概念.这允许您在集合(模型)中"允许""哪些字段",这是"绑定"的,以及可以包含哪种"类型"数据.

您当然可以采用"无模式"方法,但仍然必须定义"绑定"到模型的模式对象,而不是"严格":

var personSchema = new Schema({ },{ "strict": false });
mongoose.model( "Person", personSchema );
Run Code Online (Sandbox Code Playgroud)

然后,您几乎可以添加任何您想要的数据作为数据,没有任何限制.

相反的情况是人们"通常"确实需要强制执行某些类型的规则,例如哪些字段和类型.这意味着只有"已定义"的事情才会发生:

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" }
});
Run Code Online (Sandbox Code Playgroud)

所以那里的规则分解为:

  1. "name"只能包含"String"数据.这里有一些JavaScript习惯用法,因为JavaScript中的所有内容都会实际字符串化.这里的另一件事是"必需",因此如果发送给.save()它的对象中不存在此字段,则会抛出验证错误.

  2. "年龄"必须是数字.如果.save()使用此字段中提供的数字以外的数据尝试此对象,则会抛出验证错误.

  3. "sex"必须再次成为一个字符串,但这次我们添加一个"约束"来说明有效值是什么.同样,如果您不提供正确的数据,这也会抛出验证错误.

  4. "children"实际上是一个项目数组,但这些只是指向另一个模型中不同项目的"引用"ObjectId值.或者在这种情况下这一个.因此,当您添加到"children"时,这将保留ObjectId引用.实际上.populate(),当被要求时,Mongoose可以实际使用它们的实际"人物"对象.这模仿了MongoDB中的一种"嵌入"形式,但是当你真正想要单独存储对象而不是每次"嵌入"时使用它.

  5. "country"再次只是一个String并且不需要任何特殊内容,但如果没有明确提供其他内容,我们会给它一个默认值来填写.


你可以做很多其他事情,我建议你仔细阅读文档.那里的所有内容都有很详细的解释,如果你有特定的问题,你可以随时问"这里"(例如).

所以MongoDB对SQL数据库的工作方式做了不同的事情,并抛出了一些通常在"意见"中保存的东西,无论如何都要在应用程序业务逻辑层更好地实现.

因此,在Mongoose中,它试图"回放"人们喜欢使用传统关系数据库的一些好东西,并允许在不编写其他代码的情况下轻松封装某些规则和良好实践.

还有一些逻辑有助于"模仿"(不能强调)"加入",因为有些方法可以"帮助"您从其他来源检索"相关"数据,实质​​上提供定义"模型"该数据驻留在"模式"定义中.

我是否也没有提到"架构"定义只是对象并且可以重复使用?嗯,是的,它们实际上可以绑定到"很多"模型,这些模型可能存在也可能不存在于同一个数据库中.

这里的一切都比你目前所了解的功能和目的要多得多,这里提出了很好的建议并且"学习".这是实现的通常途径......"哦,现在我明白了,这就是他们这样做的方式".