Bootstrap

设计用户模块的schema

schema

在计算机科学中,schema通常指的是 数据结构的定义约束

关系型数据库

在关系型数据库中,schema指的是数据库中所有表格的定义和表格之间的关系约束,包括每个表格的列名、数据类型、主键、外键等等。

如果要对一个关系型数据库进行查询或修改操作,就必须先定义好相应的schema。

NoSQL数据库

在NoSQL数据库中,schema的概念略有不同。

NoSQL数据库通常分为:

  • 文档型数据库、
  • 键-值型数据库、
  • 列族存储型数据库
  • 图形数据库等几种类型

在这些数据库中,schema可以理解为数据模型的定义。

与关系型数据库相比,NoSQL数据库更加灵活,允许存储非结构化或半结构化数据,因此其schema通常也比较宽松。

例如,在MongoDB中,用于定义模型的工具Mongoose提供了对数据模型的定义和约束,包括集合(类似于关系型数据库的表)和文档的字段、数据类型、索引等方面的约束。

MongoDB 中 schema (“模型”)

MongoDB是一种非关系型数据库,它没有传统意义上的“schema”概念。

相比于关系型数据库中需要在创建表时定义固定的列(字段)和数据类型,MongoDB存储的文档可以包含各种不同结构的数据,每个文档的字段也可以动态添加或删除。

而在使用MongoDB时,我们通常需要确保应用程序对文档中所需数据存在一些共同的约定,比如使用相同的字段名、数据类型等,以便于应用程序能够正确地解析和使用这些数据。

这些约定可以称之为 “模型”,这也是在MongoDB中最接近于“schema”的概念。

在MongoDB中通常会使用Mongoose这样的工具来定义数据模型,其中包括对于集合(类似于关系型数据库的表)和文档的字段、数据类型、索引等方面的约束。

但是这些约束是可选的,同时也可以在运行时进行修改。

因此,MongoDB更加灵活,适用于需要频繁变化的数据结构或者不确定的数据模型场景。

更多精彩内容,请微信搜索“前端爱好者戳我 查看

上面说过在 MongoDB 中,模型是由 Schema 对象 定义的数据结构。 那么Schema到底是什么?

Schema 是一个 JavaScript 对象,定义了文档中字段的类型、验证规则、默认值等属性。

通过定义 Schema,可以为文档指定一组预定义的属性和方法,使文档更加结构化和可靠。

在创建模型时,我们需要将定义好的 Schema 作为参数传入 Mongoose 的 model() 方法中,以便 Mongoose 将其编译为模型。

模型可以被视为与数据库交互的对象,可以用来执行 CRUD 操作,查询文档,更新文档等操作。

在使用 MongoDB 和 Mongoose 进行开发时,定义模型并使用它们来操作数据是非常常见的操作。

通常情况下,我们会根据实际需求定义多个不同的模型,每个模型对应一种数据类型,以便更好地组织和管理数据。

设计用户模块的schema

用户模块

用户模块是指在程序中负责**管理用户信息权限**的模块。

该模块通常包括以下功能:

  • 用户注册登录:允许用户通过输入用户名和密码等信息注册新用户,或使用已有账号进行登录。
  • 用户信息管理:可以编辑和查看用户信息,例如昵称、邮箱、头像等。
  • 权限管理:对于不同的用户角色,可以控制其所能访问的页面、功能,以及具体的操作权限。
  • 安全性管理:保护用户数据安全,包括防止SQL注入、XSS攻击等攻击方式,并对用户密码等敏感信息进行加密存储。
  • 第三方登录:支持用户通过第三方平台(如微信、QQ、微博)进行快捷登录,并绑定相应账号。
  • 记住密码自动登录:可以让用户在下次登录时自动填写用户名和密码,提高用户体验。

在实现用户模块时,需要先设计数据库表结构,包括用户信息表、角色表、权限表、登录日志表等,并根据业务需求实现相应的API接口和前端页面。

同时,需要考虑到用户数据的安全性和隐私保护,例如对密码进行加密存储,采用HTTPS协议传输数据等措施。

下面仅说一下用户信息表的schema。

开始之前,先介绍mongoose创建schema中用到的几个api

mongoose.Schema()

mongoose.Schema()是Mongoose中用于定义MongoDB文档结构的构造函数。

通过它,可以创建一个新的Schema对象,用于约束MongoDB集合中文档的结构和属性。

在定义Schema时,可以使用各种类型的数据,包括:

  • 字符串
  • 数字
  • 日期等基本类型
  • 嵌套其他Schema对象或者数组,
  • 添加虚拟属性等。

此外,还可以为每个字段配置默认值验证规则索引等属性,以及自定义实例方法和静态方法。

mongoose.model()

mongoose.model()是Mongoose中用于创建数据模型的方法。

数据模型是用来定义MongoDB集合(类似于关系型数据库中的表)中文档结构、字段类型、默认值、验证规则等的约束条件。

使用mongoose.model()方法,可以将一个JavaScript对象转换为Mongoose的数据模型。

该方法接受两个参数:

  • 第一个参数为模型名称(对应MongoDB集合名称),
  • 第二个参数为模型定义对象。

其中,模型定义对象通常包括以下属性:

  • 字段名:每个字段都可以指定其类型、默认值、验证规则、索引等属性。
  • 静态方法:在数据模型上定义静态方法,可通过模型名称调用。
  • 实例方法:在数据模型原型上定义实例方法,在每个文档对象上都可以调用。
  • 虚拟属性:在文档对象中定义虚拟属性,它们不会被存储到数据库中,而是由其他字段计算得出。

设计用户模块的schema

第一步:在项目根目录新建models文件夹用于存储models文件

第二步:在models文件夹内新建用户模块的schema – users.js

需要进行下面步骤:

  1. 导入mongoose – let mongoose = require('mongoose')
  2. 实例化Schema – let schema = new mongoose.Schema()
  3. 创建模型对象 – let Users = mongoose.model('users', schema) – 第一个参数为模型名称(对应MongoDB集合名称,第二个参数为模型定义对象(规则)
  4. 导出模型对象 – module.exports = Users

全部代码

//  导入mongoose 
let mongoose = require('mongoose')

// 实例化Schema
const userSchema = new mongoose.Schema({
    username: String,
    pwd: String
})

// 创建模型对象
const User = mongoose.model('users', userSchema)

// 导出模型对象
module.exports = Users

第三步:在路由中使用用户模块的schema – users.js

var router = require('koa-router')();

const Users = require('../models/users') // 引入users modal 

router.prefix('/users');

// 添加系统用户 
router.post('/add', async (ctx) => {
  let { username, pwd } = ctx.request.body
  await Users.create({ username, pwd }).then(rel => {
    if (rel) {
      ctx.body = {
        code: 200,
        msg: '添加成功',
        data: rel
      }
    } else {
      ctx.body = {
        code: 300,
        msg: '添加失败'
      }
    }

  }).catch(err => {
    ctx.body = {
      code: 400,
      msg: '添加时出现异常'
    }
    console.error(err)
  })

})

module.exports = router;

在上面的示例代码中,在路由文件users中使用const Users = require('../models/users') , 引入users modal。

添加系统用户调用使用users modal模块。

其他复杂实例

实例一

// userSchema
const mongoose = require('mongoose');

// 创建用户Schema
const userSchema = new mongoose.Schema({
    username: {
        type: String,
        required: true, // 必填项
        unique: true,   // 唯一索引
        lowercase: true // 存入数据库前将其转换为小写
    },
    password: {
        type: String,
        required: true,
        select: false    // 查询时不返回该字段
    },
    email: {
        type: String,
        required: true,
        match: /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/,
        unique: true
    },
    age: {
        type: Number,
        min: 18,         // 最小值
        max: 60          // 最大值
    },
    created: {
      type: Date,
      default: Date.now
    },
    friends: [{
      type: mongoose.Schema.Types.ObjectId,
      ref: 'User'
    }]
});

// 创建虚拟属性
userSchema.virtual('fullName').get(function() {
    return this.firstName + ' ' + this.lastName;
});

// 创建实例方法
userSchema.methods.sayHello = function() {
    console.log(`Hello, ${this.username}!`);
}

// 创建静态方法
userSchema.statics.findByUsername = function(username, callback) {
    return this.findOne({ username: username }, callback);
}

// 导出用户Schema
module.exports = userSchema;

在上面的示例代码中,首先创建了一个用户Schema对象,并为其定义了username、password、email、age、created和friends属性。

每个属性都有其特定的类型和属性,如数据类型、是否必填、最大值最小值、正则表达式等。

然后,通过virtual方法创建一个fullName虚拟属性,以及methods方法创建一个sayHello实例方法,statics方法创建一个findByUsername静态方法。

最后,将该Schema对象导出供其他文件使用。

使用Schema对象创建mongoose数据模型时,需要在第二个参数传入该Schema对象,如下所示:

// models/user
const mongoose = require('mongoose');
const userSchema = require('./userSchema');

const User = mongoose.model('User', userSchema);

module.exports = User;

这样,在其他文件中引用此模型即可,如下所示:

const User = require('./models/user');

const user = new User({
  username: 'admin',
  password: '123456',
  email: '[email protected]',
  age: 27
});

user.save(function(err, doc) {
  if (err) {
    console.error(err);
  } else {
    console.log(doc);
  }
});

实例二

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

// 创建用户数据模型
const UserSchema = new Schema({
  name: { type: String, required: true },
  age: { type: Number, default: 18 },
  email: { type: String, required: true },
  password: { type: String, required: true },
  createdAt: { type: Date, default: Date.now }
});

// 创建模型并导出
module.exports = mongoose.model('User', UserSchema);

上述代码中,首先使用mongoose.Schema()方法定义了一个用户数据模型的结构,并将其存储在UserSchema中。

然后使用mongoose.model()方法,将UserSchema转换为一个名为“User”的model对象,并导出该对象。

这样,在其他的文件中就可以通过require()方法来引用该model对象,并进行MongoDB数据库的操作了。

例如:

const mongoose = require('mongoose');
const User = require('./models/user');

mongoose.connect('mongodb://localhost/test');
const db = mongoose.connection;

db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
  console.log('Connected to MongoDB');

  // 创建一个新用户
  const user = new User({
    name: 'Alice',
    age: 20,
    email: '[email protected]',
    password: '123456'
  });

  // 将新用户保存到集合中
  user.save(function(err, doc) {
    if (err) return console.error(err);
    console.log(doc);
  });
});

在上述示例代码中,首先使用mongoose.connect()方法连接了MongoDB数据库,然后使用require()方法引入了之前定义的User模型。

接着创建了一个新用户对象,并调用save()方法将其保存到数据库中。

每日一课:正则表达式

正则表达式是一个用于匹配文本的模式,可以使用特定的语法规则来表示各种匹配模式。

在JavaScript中,可以使用RegExp对象来创建和操作正则表达式。

正则表达式可以用于各种字符串处理任务,例如搜索、替换、验证等。

下面是一些基本的正则表达式概念:

  • 字符集:用于匹配一组字符中的任何一个字符。例如,[abc]可以匹配a、b或c,还可以使用范围表示法[a-z]、 [^abc]表示不匹配a、b和c。
  • 元字符:用于表示特殊字符或者特殊的用途。一些常见的元字符包括.、*、+、?、\、|、^、$、(、)等。
  • 量词:用于指定匹配次数。例如,?表示零次或一次,*表示零次或多次,+表示一次或多次,{n}表示恰好匹配n次,{n,m}表示匹配n到m次。
  • 边界匹配符:用于匹配字符串的边界,例如^表示匹配字符串的开头,$表示匹配字符串的结尾。

下面是一些示例正则表达式及其含义:

  • /a/:匹配字符串中第一个出现的字符a。
  • /abc/:匹配字符串中连续出现的字符串abc。
  • /\d/:匹配一个数字字符。
  • /\w/:匹配一个字母、数字或下划线字符。
  • /^[a-z]+$/:匹配只包含小写字母的字符串。
  • /^\d{3}\-\d{3}\-\d{4}$/:匹配电话号码格式,例如123-456-7890。

在JavaScript中,可以使用RegExp对象的构造函数或者字面量语法来创建正则表达式。

例如:

// 通过RegExp构造函数创建正则表达式
const pattern1 = new RegExp('ab+c');

// 通过字面量语法创建正则表达式
const pattern2 = /ab+c/;

然后可以使用正则表达式的各种方法,如test()、exec()等,进行文本匹配和替换操作,

const str = 'Hello, world!';
const pattern = /world/;
console.log(pattern.test(str)); // true
console.log(str.replace(pattern, 'JavaScript')); // Hello, JavaScript!

例如:

const str = 'Hello, world!';
const pattern = /world/;
console.log(pattern.test(str)); // true
console.log(str.replace(pattern, 'JavaScript')); // Hello, JavaScript!

正则表达式是一种强大的工具,用于处理各种文本匹配、替换、验证等任务。在JavaScript中,可以使用RegExp对象进行正则表达式操作。

;