vip课程

SchemaTypes

SchemaType 处理字段路径各种属性的定义( defaults, validation, getters, setters, field selection defaults for queries, and other general characteristics for Strings and Numbers)

以下是 mongoose 的所有合法 SchemaTypes:

Example

var schema = new Schema({
  name:    String,
  binary:  Buffer,
  living:  Boolean,
  updated: { type: Date, default: Date.now },
  age:     { type: Number, min: 18, max: 65 },
  mixed:   Schema.Types.Mixed,
  _someId: Schema.Types.ObjectId,
  decimal: Schema.Types.Decimal128,
  array:      [],
  ofString:   [String],
  ofNumber:   [Number],
  ofDates:    [Date],
  ofBuffer:   [Buffer],
  ofBoolean:  [Boolean],
  ofMixed:    [Schema.Types.Mixed],
  ofObjectId: [Schema.Types.ObjectId],
  ofArrays:   [[]],
  ofArrayOfNumbers: [[Number]],
  nested: {
    stuff: { type: String, lowercase: true, trim: true }
  }
})

// example use

var Thing = mongoose.model('Thing', schema);

var m = new Thing;
m.name = 'Statue of Liberty';
m.age = 125;
m.updated = new Date;
m.binary = new Buffer(0);
m.living = false;
m.mixed = { any: { thing: 'i want' } };
m.markModified('mixed');
m._someId = new mongoose.Types.ObjectId;
m.array.push(1);
m.ofString.push("strings!");
m.ofNumber.unshift(1,2,3,4);
m.ofDates.addToSet(new Date);
m.ofBuffer.pop();
m.ofMixed = [1, [], 'three', { four: 5 }];
m.nested.stuff = 'good';
m.save(callback);

SchemaType 选项

你可以直接声明 schema type 为某一种 type,或者赋值一个含有 type 属性的对象。

var schema1 = new Schema({
  test: String // `test` is a path of type String
});

var schema2 = new Schema({
  test: { type: String } // `test` is a path of type string
});

除了 type 属性,你还可以对这个字段路径指定其他属性。 如果你要在保存之前要把字母都改成小写:

var schema2 = new Schema({
  test: {
    type: String,
    lowercase: true // Always convert `test` to lowercase
  }
});

lowercase 属性只作用于字符串。以下有一些全部 type 可用的选项和一些限定部分 type 使用的选项。

全部可用
  • required: 布尔值或函数 如果值为真,为此属性添加 required 验证器
  • default: 任何值或函数 设置此路径默认值。如果是函数,函数返回值为默认值
  • select: 布尔值 指定 query 的默认 projections
  • validate: 函数 adds a validator function for this property
  • get: 函数 使用 Object.defineProperty() 定义自定义 getter
  • set: 函数 使用 Object.defineProperty() 定义自定义 setter
  • alias: 字符串 仅mongoose >= 4.10.0。 为该字段路径定义虚拟值 gets/sets
var numberSchema = new Schema({
  integerOnly: {
    type: Number,
    get: v => Math.round(v),
    set: v => Math.round(v),
    alias: 'i'
  }
});

var Number = mongoose.model('Number', numberSchema);

var doc = new Number();
doc.integerOnly = 2.001;
doc.integerOnly; // 2
doc.i; // 2
doc.i = 3.001;
doc.integerOnly; // 3
doc.i; // 3
索引相关

你可以使用 schema type 选项定义MongoDB indexes

  • index: 布尔值 是否对这个属性创建索引
  • unique: 布尔值 是否对这个属性创建唯一索引
  • sparse: 布尔值 是否对这个属性创建稀疏索引
var schema2 = new Schema({
  test: {
    type: String,
    index: true,
    unique: true // Unique index. If you specify `unique: true`
    // specifying `index: true` is optional if you do `unique: true`
  }
});
String
  • lowercase: 布尔值 是否在保存前对此值调用 .toLowerCase()
  • uppercase: 布尔值 是否在保存前对此值调用 .toUpperCase()
  • trim: 布尔值 是否在保存前对此值调用 .trim()
  • match: 正则表达式 创建验证器检查这个值是否匹配给定正则表达式
  • enum: 数组 创建验证器检查这个值是否包含于给定数组
Number
  • min: 数值 创建验证器检查属性是否大于或等于该值
  • max: 数值 创建验证器检查属性是否小于或等于该值
Date
  • min: Date
  • max: Date

使用注意

Dates

内建 Date 方法 不会触发 mongoose 修改跟踪逻辑, 如果你对使用 setMonth() 修改文档里的 Date, mongoose在 doc.save() 的时候是察觉不到这个文档发生了变化的,因此保存不到数据库。 如果你一定要用内建 Date 方法, 请手动调用 doc.markModified('pathToYourDate') 告诉 mongoose 你修改了数据。

var Assignment = mongoose.model('Assignment', { dueDate: Date });
Assignment.findOne(function (err, doc) {
  doc.dueDate.setMonth(3);
  doc.save(callback); // THIS DOES NOT SAVE YOUR CHANGE

  doc.markModified('dueDate');
  doc.save(callback); // works
})

Mixed

一个啥都可以放的 SchemaType , 虽然便利,但也会让数据难以维护。 Mixed 可以通过 Schema.Types.Mixed 或 传入一个空对象定义。以下三种方法效果一致:

var Any = new Schema({ any: {} });
var Any = new Schema({ any: Object });
var Any = new Schema({ any: Schema.Types.Mixed });

因为这是个 schema-less type, 所以你可以赋值为任意类型, 但是 mongoose 无法自动检测并保存你的修改。 要告诉 Mongoose 你修改了 Mixed type 的值,调用 文档的 .markModified(path) 方法, 传入你的 Mixed 字段路径。

person.anything = { x: [3, 4, { y: "changed" }] };
person.markModified('anything');
person.save(); // anything will now get saved

ObjectIds

要指定类型为 ObjectId,在声明中使用 Schema.Types.ObjectId

var mongoose = require('mongoose');
var ObjectId = mongoose.Schema.Types.ObjectId;
var Car = new Schema({ driver: ObjectId });
// or just Schema.ObjectId for backwards compatibility with v2

Arrays

创造 SchemaTypes子文档数组。

var ToySchema = new Schema({ name: String });
var ToyBox = new Schema({
  toys: [ToySchema],
  buffers: [Buffer],
  string:  [String],
  numbers: [Number]
  // ... etc
});

注意:指定空数组相当于 Mixed。以下操作相当于创建 Mixed 数组:

var Empty1 = new Schema({ any: [] });
var Empty2 = new Schema({ any: Array });
var Empty3 = new Schema({ any: [Schema.Types.Mixed] });
var Empty4 = new Schema({ any: [{}] });

数组的默认值是 [] (空数组)。

var Toy = mongoose.model('Test', ToySchema);
console.log((new Toy()).toys); // []

要手动把默认值设置为 undefined,从而覆盖 []

var ToySchema = new Schema({
  toys: {
    type: [ToySchema],
    default: undefined
  }
});

创建自定义 Type

Mongoose 可以扩展自定义 SchemaTypes。搜索 插件 页面,查找类似mongoose-long, mongoose-int32以及其他 types 的兼容 types。

schema.path() 函数

schema.path() 函数为给定字段路径返回实例化 schema type。

var sampleSchema = new Schema({ name: { type: String, required: true } });
console.log(sampleSchema.path('name'));
// Output looks like:
/**
 * SchemaString {
 *   enumValues: [],
 *   regExp: null,
 *   path: 'name',
 *   instance: 'String',
 *   validators: ...
 */

这个函数可以检查给定字段路径的检验器和类型等信息。

下一步

这章我们介绍了 SchemaTypes,下一个章节将会介绍 Connections