前端笔记之NodeJS(四)MongoDB数据库&Mongoose&自制接口&MVC架构思想|实战 - Go语言中文社区

前端笔记之NodeJS(四)MongoDB数据库&Mongoose&自制接口&MVC架构思想|实战


一、MongoDB数据库

1.1 NoSQL简介

随着互联网web2.0网站的兴起,传统的SQL数据库(关系数据库)在应付web2.0网站,特别是超大规模和高并发的SNSsocial network system,人人网)类型的web2.0纯动态网站已经显得力不从心,暴露了很多难以克服的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题。

 

传统的数据库MySQLSQL ServerOracleAccess都是SQL结构型数据库

这些结构型数据库的特点,就是“表”有明确的“字段()”的概念,而且字段是固定的。如果要增加字段,所有已经存在的条目都要改变。

SQL的优点就是查询可以很复杂,比如检索所有“语文成绩大于数学成绩且英语成绩在班级前三名的女生”。

但是在现在,你会发现很多时候检索可以很简单,不需要那么复杂。比如话费详单,没有任何需求去检索:通话时长在5分钟以上且是夜间主动拨打的。

 

结构型数据库的缺点:如果今后需要增加字段,之前的所有的条目,也要一起增加。比如你的条目已经有2万条,此时如果突然要增加一个语文成绩字段,此时20000条已经存在的条目都要进行字段的改变,此时特别耗费时间。也就是说灵活性不够!

结构型数据库的优点:查找快、有主键的概念、从键、主从查找、映射等等的高级数据库的概念。

 

SQL在这个时代:优点被缩小了,缺点被放大

如果只需要保存,并不需要精确查找,NoSQL数据库非常合适。

 

中国联通的上网记录,每个人都会有一堆数据,这个数据就是:只要存,基本上不需要查找。并且经常结构会经常变。

 

所以MySQL等等结构型数据,他们的优点(查找快、主从查找高级功能)我们越来越不用了,缺点(结构难以变化)我们需求越来越大。所以人类开始反思SQL型数据库了。

所以诞生叫做NoSQL,非关系型数据库。数据没有行、列的概念,使用k-v对儿或者JSON进行存储。优缺点正好和SQL型反过来了,适合结构变化,不适合精确查找。刚好适应了时代“只要存储,不要查找”。

NoSQL有一个昵称,叫做Not Only SQL,不仅仅是数据库。实际上是玩笑话,功能比SQL弱太多了。

 

介绍两种工作中最常用的数据库:MongoDB(文档型数据库)Redis(K-V对型数据库),他们都是NoSQL

文档型数据库(比如MongoDB)优点:数据结构要求不严格,表结构可变,不需要像关系型数据库一样需要预先定义表结构。

 

非关系型数据库现在已经广泛的应用于:社交平台、APP通信记录、银行流水、电信通话详单等等。任何只需要保存,但是不需要精确查找的使用场景,都可以用非关系型数据库。

NoSQL非关系型数据库,每一个条目的字段是不固定的。以MongoDB为例子:

{"name":"小明","age":12,"sex":"男"}
{"name":"小红","age":13,"sex":"女"}
{"name":"小刚","age":14,"sex":"男", "chengji":99}
{"name":"小黑","age":14,"sex":"男", "gongzi":5000}

1.2 MongoDB数据库安装

工作的时候是严格前后端分开的,我们学习前端不需要学习数据库的知识,但是为了模拟一个项目,更重要的是,让你了解后台和前端的交互模式,所以必须学习数据库,要有全栈思维。

 

MongoDB是一种NoSQLNo Only SQL,非关系型数据库)数据库。

MongoDB并不是什么软件,而是一堆CLI(命令行程序)。

 

MongoDB是绿色的,也就是说不需要安装,解压缩就能用。

官网:https://www.mongodb.com/

下载地址:https://www.mongodb.com/download-center

 

解压缩到你电脑盘符(不要出现中文):C:Program Files

 

解压缩之后的画风是这样的:

bin文件夹中提供的exe文件,不要双击运行,而是应该在cmd中运行,它们都是CLI程序: 

 

 

此时要将这个bin文件夹设置为系统的环境变量,就能保证CMD在任何盘符下可以运行他们。

 

 

计算机右键点击属性

 

 

如图更改环境变量

 

 

bin文件夹的路径复制进去。

 

 

打开CMD,在任意盘符下输入

mongo -version

就能查看版本,

 

如果环境变量没有设置对,会报错。

 

数据库的使用需要你安装windows补丁:KB2731284

如果补丁安装不上,查看一下方法:

 https://jingyan.baidu.com/article/fd8044fa3c47e15031137acd.html


1.3数据库的开机

c盘创建一个文件夹叫database,打开cmd输入:

mongod --dbpath c:database

mongod 表示开机命令,数据库会被打开,--dbpath表示选择一个数据库的位置。

 

 

不要关闭这个CMD,关闭了数据库也就关闭了,此时请打开一个新的CMD窗口做其他操作:

mongo

进入MongoDBREPL环境

 


1.4数据库的使用

先开机,然后新建一个CMD仓库,用mongo命令管理数据,cmd中输入mongo回车

下面的操作试着看,在mongoREPL环境中是 > ,而不是C:Usersadmin>CMD环境:

创建(切换)数据库:

use student

 

插入数据:

db.banji0902.insert({"name":"小明", "age":12})

 

查询所有:

db.banji0902.find()

 

精确查询:

db.banji0902.find({"name":"小明"})

1.5 MongoDB层次结构

MongoDB中从大到小:Database > collections > documents > records

来自: https://docs.mongodb.com/manual/introduction/

3.5.1 records条目和documents 文档

record(条目)

MongoDB中记录是一个文件,这是一个数据结构由字段和值对。MongoDB文档类似于JSON对象。字段的值可以包括其他文档、数组和文档数组。

 

documents中的一个document也称为一个record条目,条目类似JSON结构,是k-v对的,值可以是其他对象、数组、对象数组。


1.5.2 collections 集合(表)

MongoDB使用collections集合存储文档(records),集合就相当于SQL中的“表格”。但是不像表格一样,集合不需要文档拥有相同的结构(schema)。

 

下面是一个集合,里面有4个文档,文档中有3个条目(nameagesex

{"name":"小明","age":12,"sex":"男"}
{"name":"小红","age":14,"sex":"女"}
{"name":"小黑","age":14,"sex":"男"}
{"name":"小篮","age":13,"sex":"男"}

文档存储在集合(表)中,集合又存储在数据库中。


1.5.3 database数据库

数据库中可以有很多个集合(表)。


1.6常见的CMD命令

控制mongodb一般都是使用CMD命令,但也有可视化数据库软件。

 

命令有两种:

CMD命令

REPL命令(用mongo就可以进入此环境,在小尖角号“>”提示符下输入)

 

先学习CMD中能运行哪些命令?

mongod表示开机,mongo表示进入数据库的REPL环境、mongoimport导入数据、mongoexport导出数据。

 

先开机,今后一切操作必须先开机:

mongod --dbpath c:database

首先要准备好外部的数据,写几个文档,必须是.txt文件,而不是.json文件

 

导入数据,新建一个CMD窗口,输入:

mongoimport -d student -c banji0902 ./模拟数据.txt

 

 删除旧数据,导入新数据

mongoimport -d student -c banji0902 ./模拟数据.txt --drop

 

 导出指定的数据库和集合(表)中的数据:

mongoexport -d student -c banji0902 -o c:haha.txt
-d     表示指定的数据库
-c  表示指定的表名
-o  表示导出路径
--drop 表示清空之前的数据

1.7常见的REPL命令

在开机之后,另一个CMD窗口,输入mongo按回车进入数据库的REPL环境,即可操作数据库。

 

切换(创建)某一个数据库:

use student

 

查询当前有哪些数据库:

show dbs

 

查看当前数据库有哪些集合(表)

show collections

 

删除数据库:

db.dropDatabase()

 

在表中插入数据:

db.banji0902.insert({"name":"小明", "age":12})

 

查询表中所有的数据:

db.banji0902.find()

 

精确查询:

db.banji0902.find({"name":"小明"})

 

且查找:查找年龄是18,并且是男的

db.banji0902.find({"sex":"男", "age":18})

 

或($or)查找:查找年龄是18岁或“男”

db.banji0902.find({$or:[{"sex":"男"}, {"age":38}]})

 

大于($gt):

db.banji0902.find({"age":{$gt:18}})

 

大于等于($gte)、小于($lt)、小于等于($lte

 

 

查找男生,并且年龄介于1825之间:

db.banji0902.find({"sex":"男", "age":{$gte:18, $lte:25}})

 

查询中可以用正则表达式:

db.banji0902.find({"name":/小/g})

 

查询喜欢斗地主的人:

db.banji0902.find({"hobby":"斗地主"})

 

修改($set):

db.banji0902.update({"name":"小1"}, {$set:{"sex":"不男不女"}})

 

删除某条数据:

db.banji0902.remove({"name":"小1"})


1.8 MongoDBNodejs连接

官方APIhttp://mongodb.github.io/node-mongodb-native/2.2/

增删改查(CRUD)操作:http://mongodb.github.io/node-mongodb-native/2.2/tutorials/crud/

安装mongodb的依赖,并且安装指定的版本号,不要安装最新版:

npm install mongodb@2.2.28 --save

注意:mongodb版本的API是不一样的,所以要看官方文档:

 http://mongodb.github.io/node-mongodb-native/3.0/

 

var MongoClient = require("mongodb").MongoClient; //引包

//数据库地址
var dbUrl = 'mongodb://127.0.0.1:27017/student';
//连接数据库
MongoClient.connect(dbUrl, function(err,db){
    if(err){
        console.log("数据库连接失败");
        return;
    }

    console.log("数据库连接成功!");
    db.close();
})

 

查询数据:

var MongoClient = require("mongodb").MongoClient; //引包

//数据库地址
var dbUrl = 'mongodb://127.0.0.1:27017/student';
//连接数据库
MongoClient.connect(dbUrl, function(err,db){
    if(err){
        console.log("数据库连接失败");
        return;
    }

    console.log("数据库连接成功!");

    //查询当前数据库中banji0902表的数据
    db.collection("banji0902").find({"age":{$gt:18}}).toArray(function(err,data){
        console.log(data);
        db.close();
    })
})

传统的连接形式限制一般不用了,因为:

l 回调函数难看。

不方便MVC编程

原生API复杂


二、Mongoose数据库

2.1新增数据

官网:https://mongoosejs.com/

node.js的优雅mongodb对象建模。

安装依赖:

npm install --save mongoose@4

 

写一个Hello World。套路:引包、创建schema、创建模型、实例化模型、调用save()方法。

var mongoose = require("mongoose"); //引包

//连接数据库,数据库叫iqd,如果数据库不存在会自动创建
mongoose.connect("mongodb://127.0.0.1:27017/iqd", {useMongoClient:true});

//创建一个数据库结构(Schema)
var studentSchema = {
    name:String,
    age:Number,
    sex:String
}

//创建模型(会返回一个类),student是表名称(集合)
//注意:在nodejs中创建的表面叫“student”,但是到了数据库中会自动加上s,变成“students”
var Student = mongoose.model('student', studentSchema);

//new一个实例
var xiaoming = new Student({"name":"小明","age":12,"sex":"男"});

//保存数据
xiaoming.save();

 

运行node app.js

iqd数据自动创建,并且创建了一个叫student的表(数据库会自动加s),所以变成students

 

开机、REPL、控制台各一个CMD

 

mongoose就是这样的哲学:让开发者感觉不到在操作数据,仅仅通过new save等类、实例的方法,就能管理数据库,除了newsvae()能创建数据,用Student.insert({})也能创建数据库。


2.2查找

//查询数据库的方法1:
Student.find({"age":{$gt:18}}, function(err,data){
    console.log(data)
})

//查询数据库的方法2:
Student.find({"age":{$gt:18}}).exec(function(err,data){
    console.log(data)
})
查找

2.3删除

删除方法很灵活,可以用类打点调用Studentremove方法

//删除的方法1
Student.remove({"name":"小黑"}, function(err,data){
    console.log(data)
})

//删除的方法2:
Student.remove({"name":"小黑"}).exec(function(err,data){
    console.log(data)
})
类打点

 

也可以调用实例的remove()方法删除

Student.find({"name":"小6"}, function(err,data){
    var xiao6 = data[0];
    xiao6.remove(); //删除
})
调用实例

2.4修改

Student.find({"name":"小3"}, function(err,data){
    var xiao3 = data[0];
    xiao3.sex = "不男不女"; //赋值修改
    xiao3.save();
})
mongoose修改

 

如果不用mongoose,用原生

db.collections("students").update({"name":"小3"}, {$set:{"sex":"不男不女"}})

2.5封装静态方法

刚刚发现可以用类名(构造函数)打点调用很多方法

Student.find()
Student.remove()

那么如何自己封装一些方法呢?并且能用类打点调用,mongoose提供自定义封装类的方法(静态方法),步骤:

创建schema的时候,必须用new mongoose.Schema()创建

schema的实例上,用statics.***绑定静态方法

var mongoose = require('mongoose'); //引包
//连接数据库,数据库叫iqd,如果数据库不存在会自动创建
mongoose.connect('mongodb://localhost/iqd',{useMongoClient:true});

//创建一个数据库结构(Schema)
var studentSchema = new mongoose.Schema({
    name: String,
    age : Number,
    sex : String
})

//封装自定义的静态方法
studentSchema.statics.check = function(name,callback){
    //this表示Student类
    this.find({"name":name}, function(err,data){
        var exsit = data.length > 0;
        //将结果通过参数传递给回调函数
        callback(exsit)
    })
}

var Student = mongoose.model('student', studentSchema);

//验证某个人是否存在
Student.check("小明", function(exsit){
    console.log(exsit)
})

2.6封装动态方法

实例打点调用的都叫动态方法:

var mongoose = require('mongoose'); //引包
//连接数据库,数据库叫iqd,如果数据库不存在会自动创建
mongoose.connect('mongodb://localhost/iqd',{useMongoClient:true});

//创建一个数据库结构(Schema)
var studentSchema = new mongoose.Schema({
    name: String,
    age : Number,
sex : String,
})

//封装自定义的动态方法
studentSchema.methods.bianxing = function(name,callback){
    //this表示实例
    this.sex = this.sex == "男" ? "女" : "男";
}

var Student = mongoose.model('student', studentSchema);

//使用动态方法
Student.find({"name":"小明"}, function(err,data){
    var ren = data[0]; //实例
    ren.bianxing();
    ren.save();
    console.log(data)
})

Nodejs + MongoDB技术栈在工作中很少用到,因为有后台哥哥姐姐,学习NodejsMongoDBHTTP服务器开发的目的:

理解前端后端如何工作、配合、数据如何传递、数据库的增删改查是什么情况。

为了写一个JSON接口,给前端调用


 

三、制作一套增删改查的接口

做一套RESTful风格的路由接口,创建模拟数据:

{"id":1001,"name":"小明","age":12,"sex":"男","job":"前端"}
{"id":1002,"name":"小红","age":15,"sex":"女","job":"设计"}
{"id":1003,"name":"小刚","age":12,"sex":"男","job":"老师"}
{"id":1004,"name":"小强","age":13,"sex":"男","job":"后端"}
{"id":1005,"name":"小绿","age":18,"sex":"男","job":"老师"}
{"id":1006,"name":"小青","age":18,"sex":"女","job":"前端"}
{"id":1007,"name":"小黑","age":18,"sex":"女","job":"产品"}
{"id":1008,"name":"小花","age":18,"sex":"女","job":"设计"}

它们都是用户,所以导入到数据库时,名字叫users的表中,注意表名最后一个字母必须是s

 创建models文件夹,文件夹中创建User.js,创建数据结构

var mongoose = require('mongoose'); //引包
//默认暴露
module.exports = mongoose.model('user', {
    id:Number,
    name: String,
    age : Number,
    sex : String,
    job : String
});
数据结构

 

 app.js查询接口

var mongoose = require('mongoose'); //引包
var User = require('./models/User.js');
var express = require('express'); //引包
var app = express();

//连接数据库,数据库叫gziqd,如果数据库不存在会自动创建
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://localhost/gziqd',{useMongoClient:true});

//查询数据库全部的用户
app.get("/users", function(req,res){
    User.find().exec(function(err,data){
        res.json({"data": data})
    })
});

//查询某一个id的用户
app.get("/users/:id", function(req,res){
    var id = req.params.id;
    //指定id查询
    User.find({"id": id}).exec(function(err,data){
        res.json(data[0])
    })
});

app.listen(3000)

 

 

发出POST请求创建数据

index.html前端页面:

<html>
<head>
    <title>Document</title>
</head>
<body>
    <!-- 增加 -->
    <p>ID :<input type="text" id="idTxt" /></p>
    <p>姓名:<input type="text" id="name" /></p>
    <p>工作:<input type="text" id="job" /></p>
    <button id="btn1">创建用户</button>
    <hr>

    <!-- 删除 -->
    <p>
        删除的人的id :<input type="text" id="delId"/>
        <button id="btn2">删除</button>
    </p>
    <hr>

    <!-- 修改 -->
    <p>
        改名的人的id :<input type="text" id="changeId"/><br>
        要改为什么名 :<input type="text" id="changeToName"/>
        <button id="btn3">修改</button>
    </p>
    <hr>

    <!-- 查询 -->
    <p>
        查询id :<input type="text" id="checkId"/>
        <button id="btn4">查询</button>
    </p>
</body>
<script type="text/javascript" src="js/jquery-2.2.4.min.js"></script>
<script type="text/javascript">
     //发出POST请求,创建用户,提交给数据库(服务器)
     $("#btn1").click(function(){
        $.post("/users",{
            id : $("#idTxt").val(),
            name: $("#name").val(),
            job : $("#job").val()
        }, function(data){
            if(data == "ok"){
                alert("创建成功!");
            }
        })
     });
</script>

                            
                            版权声明:本文来源博客园,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://www.cnblogs.com/rope/p/10728717.html
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2019-11-17 16:36:41
  • 阅读 ( 3831 )
  • 分类:架构

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢