# Schema
如果你希望数据库的结构更严格一点,也可以添加 schema
GoDB
会根据 schema
建立 IndexedDB
数据表,并给相应字段建立索引
import GoDB from 'godb';
// 定义数据库结构
const schema = {
// user 表:
user: {
// user 表的字段:
name: {
type: String,
unique: true // 指定 name 字段在表里唯一
},
age: Number
}
}
const testDB = new GoDB('testDB', schema );
const user = testDB.table('user');
const data = {
name: 'luke'
age: 22
};
user.add(data) // 没问题
.then(() => user.get({ name: 'luke' })) // 定义schema后,就可以用id以外的字段获取数据
.then(luke => user.add(luke)) // 报错,name 重复了
如上面的例子,指定了 schema
后
- 定义了 schema,因此
get()
和delete()
中可以使用id
以外的字段搜索了,否则只能传入id
- 指定了
user.name
这一项是唯一的,因此无法添加重复的name
当然,你也可以在 table
那定义 schema
:
const testDB = new GoDB('testDB');
const user = testDB.table('user', {
name: {
type: String,
unique: true
},
age: Number
});
但这种方式的缺点是,如果定义 table
发生在连接数据库之后,GoDB
会先发起一个 IDBVersionChange
的事件,导致 IndexedDB
数据库版本升级,此时如果有别的 CRUD 操作正在进行,可能会导致建立 table
失败
要避免这个问题倒是很简单,把所有获取 table
的操作紧接在 new GoDB()
之后(保证连接数据库,和连接数据表,是同步而非异步执行的)就可以,这样可以确保所有 table
都在连接完成之前获取到(JS 的事件循环特性)
关于 schema 的设计
部分同学或许会发现,上面定义 schema
的方式有点眼熟,没错,正是参考了 mongoose
- 定义数据库的字段时,可以只指明数据类型,如上面的
age: Number
- 也可以使用一个对象,里面除了定义数据类型
type
,也指明这个字段是不是唯一的(unique: true
),之后会添加更多可选属性,如用来指定字段默认值的default
,和指向别的表的索引ref
不定义 Schema 时,GoDB
使用起来就像 MongoDB 一样,可以灵活添加数据;区别是 Mongodb 中,每条数据的唯一标识符是 _id
,而 GoDB
是 id
虽然这样做的问题是,IndexedDB 毕竟还是存在字段索引这个概念,用户使用不规范的话(如每次添加的数据结构都不一样),久而久之可能会使得数据库的字段比较杂,带来额外的使用成本
定义 Schema 后,GoDB
使用起来就像 MySQL 这种关系型数据库一样,无法往数据表里添加不存在的字段(GoDB 不会阻止这次添加操作,但是会去掉未定义的字段后再添加,同时在浏览器报一个 warning)
因此推荐在项目中,首先定义好 schema
,这样不管是维护性上,还是性能上,都要更胜一筹
当然不使用 schema
也是完全可行的,使用上也不会有任何问题,是否使用 schema
取决于开发者自己的取舍,如果你的应用不是很复杂,完全可以不用管 schema
,这样使用起来更灵活