设计用户模块的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: 'admin@admin.com',
  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: 'alice@example.com',
    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对象进行正则表达式操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/29652.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Leetcode-6425. 找到最长的半重复子字符串

题目描述 给你一个下标从 0 开始的字符串 s ,这个字符串只包含 0 到 9 的数字字符。 如果一个字符串 t 中至多有一对相邻字符是相等的,那么称这个字符串是 半重复的 。 请你返回 s 中最长 半重复 子字符串的长度。 一个 子字符串 是一个字符串中一段…

力扣日记2481

1. 题目 LeetCode 2481. 分割圆的最少切割次数 1.1 题意 可以使用直接或半径切分,管他叫一次切分,求切分圆为n等份的最少次数。 1.2 分析 可以想到,对圆做n等分,然后每个半径看出一次切分,这是最多次数,…

Python3 列表与元组 | 菜鸟教程(六)

目录 一、Python3 列表 (一)简介相关 1、序列是 Python 中最基本的数据结构。 2、序列中的每个值都有对应的位置值,称之为索引,第一个索引是 0,第二个索引是 1,依此类推。 3、Python 有 6 个序列的内置…

算法刷题-字符串-替换空格

题目:剑指Offer 05.替换空格 力扣题目链接 请实现一个函数,把字符串 s 中的每个空格替换成"%20"。 示例 1: 输入:s “We are happy.” 输出:“We%20are%20happy.” 思路 如果想把这道题目做到极致&…

webpack提升开发体验SourceMap

一、开发场景介绍 开发中我们不可避免的会写一些bug出来,这时候要调试,快速定位到bug到底出现在哪尤为关键。 例如我故意在sum函数中写一个错误代码如下: 这时我们用前面章节已经写好的开发模式的webpack.dev.js运行,控制台会出…

【总结笔记】Spring

1 Spring容器加载配置文件进行初始化。 Spring容器加载配置文件进行初始化主要有两种形式: 加载配置文件进行初始化: ClassPathXmlApplicationContext ctx new ClassPathXmlApplicationContext(“ApplicationContext.xml”); 加载配置类进行初始化&…

业务流程自动化:ThinkAutomation Professional Crack

ThinkAutomation 助力您的业务流程自动化。自动执行本地和基于云的业务流程,以降低成本并节省时间。 自动化传入的通信渠道,监控数据库,对传入的Webhook,Web表单和聊天机器人做出反应。处理文档、附件、本地文件和其他邮件源。 …

基于Spark的气象数据分析

研究背景与方案 1.1.研究背景 在大数据时代背景下,各行业数据的规模大幅度增加,数据类别日益复杂,给数据分析工作带来极大挑战。气象行业和人们的生活息息相关,随着信息时代的发展,大数据技术的出现为气象数据的发展…

模板匹配笔记

模板匹配是一种最基本、最原始的模式识别的方法。通过对比某一特定物体的图案位于图像的什么地方,进而识别出物体。它是图像处理中最基本、最常用的匹配方法。它的局限性主要是它只能进行平行移动,若原图像中的匹配目标发生旋转或大小变化,该…

前端vue入门(纯代码)09

【09.vue中组件的自定义事件】 自定义组件链接 在vue中用的click【点击】、keyup【按键】……等事件,这些属于内置事件,也就是js自带的事件。 问题一:什么是组件自定义事件呢? 【内置事件】:是给html元素用的,比如s…

014、数据库管理之配置管理

配置管理 TiDB配置系统配置集群配置配置的存储位置区分TiDB的系统参数和集群参数 系统参数系统参数的作用域系统参数的修改 集群参数集群参数的修改配置参数的查看 实验一: 在不同作用域下对数据库的系统参数进行修改session级别global级别 实验二: 修改…

【TCP/IP】多进程服务器的实现(进阶) - 信号处理及signal、sigaction函数

目录 信号 signal函数 sigaction函数 用信号来处理僵尸进程 在之前我们学习了如何处理“僵尸进程”,不过可能也会有疑问:调用wait和waitpid函数时我们关注的始终是在子进程上,那么在父进程上如何实现对子进程的管控呢?为此&am…

零基础速成simulink代码生成——简单滤波器实现2

simulink setting 找到model settings solver求解器配置 Code Generation 代码生成配置 生成代码报告 添加stateflow注释 可以将变量保存在定义的文件(选) 实践 简单一阶滤波器

使用一键安装工具快速搭建 ESP-IDF 开发环境 (Windows)

我们收到用户对 ESP-IDF SDK 软件开发环境感到搭建难、门槛高的反馈。为解决用户在此方面的问题。为此,我们推出本期教程介绍在 Windows 操作系统下使用一键安装工具快速搭建 ESP-IDF 开发环境。 您可以观看下面的教程视频,也可以阅读接下来本篇的图文教…

CVPR 2023 | 图像超分,结合扩散模型/GAN/部署优化,low-level任务,视觉AIGC系列

1、Activating More Pixels in Image Super-Resolution Transformer 基于Transformer的方法在低级别视觉任务中,如图像超分辨率,表现出了令人印象深刻的性能。Transformer的潜力在现有网络中仍未得到充分发挥。为了激活更多的输入像素以实现更好的重建&a…

有哪些工具软件一旦用了就离不开?

💖前言 目前,随着科技的快速发展,电脑已经进入了许许多多人的生活 ,在平日的学习、工作和生活里,我们会用的各种各样的强大软件。市面上除了某些大公司开发在强大软件,还有各路大神开发具有某些功能的强大…

Java阶段四Day01

Java阶段四Day01 文章目录 Java阶段四Day01Security框架通配符Vue脚手架 Vue-cli关于VUE关于VUE Cli创建Vue Cli工程解决端口被占用 Vue工程的工程结构[.idea]【重要】[node_modules]【重要】[public]favicon.icoindex.html [src][assets][compnents]【重要】[router][store]【…

Spring基础知识(二)

目录 1.Spring Bean是什么 2.Spring提供的配置方式 3.Spring bean中的scope 4.Spring bean容器的生命周期 5.Spring的内部bean 6.Spring装配是什么 7.自动装配模式 8.自动装配的局限性 9.基于注解配置容器 10.如何启动注解装配 1.Spring Bean是什么 Spring官方文档对…

客户端负载均衡工具Ribbon

一 什么是Ribbon Ribbon介绍 目前主流的负载方案分为以下两种: 集中式负载均衡,在消费者和服务提供方中间使用独立的代理方式进行负载,有硬件的(比如 F5),也有软件的(比如 Nginx)…

10大白帽黑客专用的 Linux 操作系统

平时在影视里见到的黑客都是一顿操作猛如虎,到底他们用的都是啥系统呢? 今天给大家分享十个白帽黑客专用的Linux操作系统。 ▍1. Kali Linux Kali Linux是最著名的Linux发行版,用于道德黑客和渗透测试。Kali Linux由Offensive Security开发&…