鉴别器(discriminator)是一种模型继承机制,可以在同一个集合(collecton)中定义不同的结构。举个例子,假如我们的业务中有两个实体 customer 和 order,正常情况下肯定是创建两个模型:
-
客户模型
const Customer = mongoose.model('Customer', new mongoose.Schema({ firstName: { type: String }, lastName: { type: String }, email: { type: String } }))
-
订单模型
const Order = mongoose.model('Order', new mongoose.Schema({ orderDate: { type: Date, default: Date.now }, items: [String] }))
然后写数据的时候分别用:
-
创建客户
const customer = new Customer({ firstName: "John", lastName: "Doe", email: "john@doe.com" }) customer.save((err, savedCustomer) => console.log(JSON.stringify(savedCustomer)))
-
创建订单
const order = new Order({ items: ["apple", "orange", "pear"] }) order.save((err, savedOrder) => console.log(JSON.stringify(savedOrder)))
这样客户集合和订单集合里面分别各有一条数据了。
但是如果利用 discriminator,我们却可以把这两个完全无关的模型放到同一个表中,举个例子,我们先创建一个 Base 模型,集合的名称叫 data,然后指定 discriminatorKey 为 __type
(如果不指定的话,默认为 __t
):
const baseOptions = { discriminatorKey: '__type', collection: 'data' }
const Base = mongoose.model('Base', new mongoose.Schema({}, baseOptions))
接下来可以让 Customer 和 Order 都继承自这个 Base 模型:
const Customer = Base.discriminator('Customer', new mongoose.Schema({
firstName: { type: String },
lastName: { type: String },
email: { type: String }
}))
const Order = Base.discriminator('Order', new mongoose.Schema({
orderDate: { type: Date, default: Date.now },
items: [String]
}))
代码改动很少,我们依然可以用 Customer 和 Order 模型来创建或查询数据,不过最终都放到了 data 集合里面,该集合的每条数据中都有一个 __type
字段用于区分类型,在上面的例子当中就是 Customer 和 Order。
那这样做有啥好处呢?就上面的例子来讲,放在一起并不合适,除非你买的云数据库是按照集合数量进行计费的,否则还是老老实实地放在两张表里面把,符合语义也方便查询。但是有些场景下,字段相似的集合就可以合并了,特别是有些表的字段是动态的,你可能选择用 Mixed 类型(这就好比 TypeScript 中的 any 一样虽然强大但无法推断具体类型),但 discriminator 或许是更好的选择。