Mongoose插入数据时字段顺序变更及其他幕后数据修改疑问
为什么Mongoose插入数据时字段顺序会变?还有哪些幕后修改?
字段顺序变更的原因
手动向MongoDB插入数据时,你直接调用的是MongoDB驱动的原始插入逻辑,MongoDB 3.4及以上版本会严格保留你传入的字段顺序。但Mongoose是基于Schema工作的——它在处理插入请求前,会按照你定义的Schema字段顺序重新构造文档对象。
另外,早期JavaScript对象并不保证属性顺序(ES6之后才明确了对象属性的排序规则),Mongoose内部处理数据时会严格遵循Schema的结构来排序字段,所以最终存入数据库的字段顺序会和你的Schema定义一致,而非你传入数据的顺序。如果需要保留传入的字段顺序,可以在Schema选项里设置{ strict: false, retainKeyOrder: true }(注意不同Mongoose版本可能有细节调整,建议对应版本文档)。
Mongoose幕后的其他数据修改
除了你提到的自动添加嵌套对象的_id和文档的__v版本号,Mongoose还会做这些隐性处理:
- 类型转换与验证:按照Schema定义的类型自动转换数据,比如把字符串格式的数字转成Number类型,把日期字符串转成Date对象;如果数据不符合类型规则,会直接抛出验证错误(手动插入MongoDB不会做这些检查)。
- 默认值填充:如果Schema里给字段设置了
default属性,插入时未传该字段的话,Mongoose会自动填充默认值,比如createdAt: { type: Date, default: Date.now }。 - 过滤未定义字段:默认情况下,Mongoose会自动移除Schema中没有定义的字段,不会将其存入数据库(手动插入的话会保留所有传入字段)。
- 钩子(Middleware)执行:自动触发你定义的预/post钩子逻辑,比如
pre('save')钩子可以在保存前加密用户密码,post('find')钩子可以在查询后处理返回数据。 - 字段别名处理:如果Schema里给字段设置了
alias,Mongoose会将传入的别名字段映射为数据库中的实际字段名,比如定义email: { type: String, alias: 'userEmail' },传userEmail会被转成email存入。 - 数组规范化:对于数组类型的字段,如果你传入单个值,Mongoose会自动将其转为数组,比如Schema定义
tags: [String],传"mongoose"会变成["mongoose"]存入。 - 虚拟属性计算:虽然虚拟属性不会存入数据库,但Mongoose会在查询或返回文档时自动计算虚拟属性的值(比如
fullName由firstName和lastName拼接而成)。 - 关联数据处理:针对Schema中定义的关联(比如
ref属性),Mongoose可以通过populate自动查询并填充关联的文档数据,省去手动关联查询的麻烦。
内容的提问来源于stack exchange,提问作者Temp O'rary
相关产品推荐
相关产品推荐

