MongoDB

总点击95
简介:1传统数据库技术回顾 数据库就是存储数据的,那么存储数据就用txt就行了啊,为什么要有数据库?

1传统数据库技术回顾

数据库就是存储数据的,那么存储数据就用txt就行了啊,为什么要有数据库?

理由之1: 数据库有行、列的概念,数据有关系,数据不是散的。


老牌数据库,比如MySQL、SQL Server、Oracle、Access。这些数据库,我们管他们叫做结构型数据库。为什么?因为每个表中,都有明确的字段,每行记录,都有这些字段。不能有的行有,有的行没有。


MongoDB

理由之2:数据库能够提供非常方便的接口,让增删改查操作变得简单


我们的老牌数据库,都无一例外的使用SQL语言,管理数据库。


SQL就是structure query language。


比如,查询所有女生: SELECT * FROM step1 WHERE xingbie = ‘女’;


再比如,查询所有女生,并且年龄20~24之间,且在北京:

SELECT * FROM step1 WHERE xingbie = '女' AND nianling < 24 AND nianling >= 20 AND xianzaisuozaidi = '北京';

理由之三:数据库不能自己玩儿,要给向PHP、.net、jsp等语言提供接口。


用php这些语言,能够向数据库之中增删改查。

老牌数据库,都是结构型数据库,现在出了什么问题?


比如,我们现在想往一个已经有1000条数据的数据库中增加一个字段“高中信息”。


MongoDB


之前已经存在的数据,实际上不需要增加这个字段。因为这些用户已经填写完毕表单了,不需要再手机高中信息了。我们的意图就是在今后注册的用户,需要填写高中信息。但是,我们刚才说了,所谓的字段,是表的一个结构。所有的行都必须拥有,不能有的行有这个字段,有的行没有这个字段。


可想而知,大数据时代,数据库中有100万条数据都算少的。我们如果要动字段,时间太长。


所以,字段这个东西,太不灵活。

数据不灵活。一个字段,需要是同样类型的数据。不能一行记录是文本,一行记录是数字。

非结构型数据库NoSQL应运而生。


NoSQL是个怪胎,无法挑战老牌数据库,但是在大数据时代有自己的意义。

2 NoSQL

NoSQL(NoSQL = Not Only SQL ),意即“不仅仅是SQL”,是一项全新的数据库革命性运动,早期就有人提出,发展至2009年趋势越发高涨。NoSQL的拥护者们提倡运用非关系型的数据存储,相对于铺天盖地的关系型数据库运用,这一概念无疑是一种全新的思维的注入。

非结构型数据库。没有行、列的概念。用JSON来存储数据。


集合就相当于“表”,文档就相当于“行”。


MongoDB

1.数据库 DataBase

● 数据库中存储众多集合。


● 数据库最终会变为文件系统里面的文件,而数据库名字就是相应的文件名,所以数据库的命名,应该遵守操作系统的文件名命名规范。


● 数据库命名不能是admin、local、config

2.集合 Collections

集合就是一组文档,相当于“表”。


MongoDB


集合中可以存储完全不同结构的文档。


MongoDB

3.文档

NoSQL中,最小的“数据条目”,不是“行”,而是“文档”。


文档就是键值对的一个集合,实际上表达方式和JSON一样。


MongoDB

文档就是JSON,但是要比JSON多了一些限制:


● 每个文档必须有一个特殊的键 _id ,这个键在集合中必须是唯一的。


● 文档中的所有键不能重复;大小写不同的键,视为不同的键。


● 文档中键的命名,不能含有.和$,其他不限,甚至可以用中文命名、阿拉伯数字。


● 文档中值的类型,比JavaScript中多了一些,比如日期、ObjectId()、正则表达式。


● 文档给程序员看的时候,是JSON的表示模式,但是实际存储的时候,是BSON方式,即用二级制方式存储。

4.总结NoSQL的特点和优势

我们总结NoSQL数据库在以下的这几种情况下比较适用:


1、数据模型比较简单;


2、需要灵活性更强的IT系统;


3、对数据库性能要求较高;


4、不需要高度的数据一致性;

我们看,有些系统,特别需要筛选。比如,筛选出所有女生大于20岁的。那么SQL型数据库,非常擅长!因为它有行、列的概念。


但是,有些系统,真的不需要进行那么多的筛选,比如站内信。站内信只需要存储就好了。不需要筛选。那么NoSQL的。

NoSQL不是银弹,没有资格挑战老牌数据库,还是特定情况下,是适合的。

3 MongoDB

1. MongoDB基本安装

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


手册:https://docs.mongodb.org/manual/


win7系统需要安装补丁,KB2731284。


MongoDB

此时,我们看一下装好的文件夹:


C:Program FilesMongoDBServer3.0bin 加入到系统的path环境变量中(这样就可以全局使用MongoDB命令了)


MongoDB

2. MongoDB基本使用

那么我们就能在系统的任何盘符,使用mongo命令了:


使用数据库: mongo


开机: mongod


导入数据: mongoimport

1.先开一个CMD:

开机命令:


MongoDB

–dbpath就是选择数据库文档所在的文件夹。(c:mongo是自己在c盘下建立mongo,也就是说我们要自己创建数据库文档所在的文件夹)


也就是说,mongoDB中,真的有物理文件,对应一个个数据库。U盘可以拷走。


一定要保持,开机这个CMD不能动了,不能关,不能ctrl+c。 一旦这个cmd有问题了,数据库就自动关闭了。

2.再开一个CMD:

输入


MongoDB

那么,运行环境就是mongo语法了。


列出所有数据库:

show dbs

使用某个数据库

use 【数据库名字】

如果想新建数据库,也是use。use一个不存在的,就是新建。(例如新建use hcd)

查看当前所在数据库

db

插入数据:


MongoDB


student就是所谓的集合。集合中存储着很多json。


student是第一次使用,集合将自动创建。

3.实例:

1号cmd


开机:

mongod --dbpath D:mongo

2号cmd

mongo //连接

show dbs //查看数据库

use hcd //新建hcd (如果你不插入数据,hcd的数据库是不会被创建的)

switched to db hcd

db //查看当前数据库

hcd

db.student.insert({"name":"hcd"}); //数据库中新建student集合,并插入数据

WriteResult({ "nInserted" : 1 })

show collections //显示所有的集合

student

system.indexes

db.student.find() //查看student集合的数据

{ "_id" : ObjectId("599c2fc210caa6deb9584e47"),"name" : "hcd" }

3. MongoDB视图软件 MongoVUE的使用

安装后打开


1.创建连接(要确定本地的mongoDB已经打开)


MongoDB


首先现按 +号(没有直接弹出框的话点左上角Connect按钮) 然后弹出窗口,name:自己想起的连接数据库的名字(不是数据库的名字),Server:127.0.0.1(本地服务地址),然后点击Save按钮

2.观察


假如:我们创建连接名字为first,数据库名字为test,集合名字books,集合中有两个文档,


按钮Tree View Table View Text View为查看文档的方式


MongoDB

4 MongoDB数据库的使用

(注意:这里是cmd的命令行方式,不用特别记住,还有Node方式)


可以查看手册https://docs.mongodb.org/manual/


MongoDB

1 插入数据

插入数据,随着数据的插入,数据库创建成功了,集合也创建成功了。

db.student.insert({"name":"xiaoming"});

我们不可能一条一条的insert。所以,我们希望用sublime在外部写好数据库的形式,然后导入数据库:


注意:mongoimport和mongo是同级的,不能在连接mongo后再执行:mongoimport命令

mongoimport --db test --collection restaurants --drop --file primer-dataset.json

-db test 想往哪个数据库里面导入


–collection restaurants 想往哪个集合中导入


–drop 把集合清空


–file primer-dataset.json 哪个文件

这样,我们就能用sublime创建一个json文件,然后用mongoimport命令导入,这样学习数据库非常方便。

例如:

mongoimport --db hcd --collection student --drop /c/Users/Administrator/Desktop/a.json

将数据存放在hcd数据库中的student的集合中,然后将json拖入命令工具中就行了

2 查找数据

查找数据,用find。find中没有参数,那么将列出这个集合的所有文档

db.restaurants.find() //(列出restaurants集合的所有数据)

精确匹配:

db.student.find({"score.shuxue":70}); // {a:{b:‘c’}} 就用“a.b”:c表示11

多个条件:

db.student.find({"score.shuxue":70,"age":12})

大于条件:

db.student.find({"score.yuwen":{$gt:50}});

寻找所有年龄是9岁,或者11岁的学生

db.student.find({$or:[{"age":9},{"age":11}]});

查找完毕之后,打点调用sort,表示升降排序。

db.restaurants.find().sort( { "borough": 1,"address.zipcode":-1 } )

//这里面表示先按照borough来升序排列,如果borough相同,则按照address.zipcode降序排列

3 修改数据

修改里面还有查询条件。你要该谁,要告诉mongo。


默认情况下更改第一个匹配的元素


查找名字叫做小明的,把年龄更改为16岁:

db.student.update({"name":"小明"},{$set:{"age":16}});

查找数学成绩是70,把年龄更改为33岁:

db.student.update({"score.shuxue":70},{$set:{"age":33}});

更改所有匹配项目:”


By default,the update() method updates a single document. To update multiple documents,use the multi option in the update() method.

db.student.update({"sex":"男"},{$set:{"age":33}},{multi: true});

完整替换,不出现$set关键字了:

db.student.update({"name":"小明"},{"name":"大明","age":16});

4 删除数据

默认情况下情况满足的都会删除

db.restaurants.remove( { "borough": "Manhattan" } )

By default,the remove() method removes all documents that match the remove condition. Use the justOne option to limit the remove operation to only one of the matching documents.


加上justOne: true表示只删除满足条件的第一个元素

db.restaurants.remove( { "borough": "Queens" },{ justOne: true } )

删除restaurants集合下的所有数据

db.restaurants.remove( {} )

5 Node.js操作MongoDB

首先:


Node.js安装MongoDB


npm install mongodb

API可以查看手册https://docs.mongodb.org/manual/


MongoDB


或者直接查看http://mongodb.github.io/node-mongodb-native/2.2/quick-start/quick-start/

案例1:


访问127.0.0.1/都会往数据库写入组对象

var express = require('express');

var app = express();

//在Node中引入mongodb模块

var MongoClient = require('mongodb').MongoClient;

//设置要链接的数据库URL,myproject为我们数据库的名字

var url = 'mongodb://localhost:27017/myproject';

//使用数据库连接服务

app.get('/',function(req,res){

// 回调函数中,err为错误,db为数据库

MongoClient.connect(url,function(err,db) {

//在数据库中简历集合'documents'

var collection = db.collection('documents');

//向集合中插入一组文档

collection.insertMany([

{a : 1},{a : 2},{a : 3}

],result) {

console.log("Inserted 3 documents into the collection");

});

//关闭数据库,正规的就是每一次操作都要打开和闭合数据库

db.close();

});

})

app.listen(3000);

结果:


MongoDB

04—案例01


案例2:


目录:


MongoDB


列出所有数据库中的数据


index.ejs:

<!doctype html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title></title>

<style type="text/css">

table,tr,td{

border:1px solid black;

border-collapse: collapse;

}

tr:nth-child(2n){

background-color: pink;

}

</style>

</head>

<body>

<h1>学生管理系统</h1>

<a href="/add">添加学生</a>

<table>

<tr>

<th>姓名</th>

<th>年龄</th>

<th>数学分数</th>

<th>语文分数</th>

</tr>

<% for(var i = 0 ; i < result.length ; i++){%>

<tr>

<td><%= result[i].name %></td>

<td><%= result[i].age %></td>

<td><%= result[i].score.yuwen %></td>

<td><%= result[i].score.shuxue %></td>

</tr>

<%}%>

</table>

</body>

</html>

add.ejs:

<!doctype html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title></title>

<style type="text/css">

</style>

</head>

<body>

<h1>学生管理系统</h1>

<form action="/tijiao" method="get">

<p>

姓名: <input type="text" name="name"/>

</p>

<p>

年龄: <input type="text" name="age"/>

</p>

<p>

数学成绩: <input type="text" name="shuxuechengji"/>

</p>

<p>

语文成绩: <input type="text" name="yuwenchengji"/>

</p>

<p>

<input type="submit"/>

</p>

</form>

</body>

</html>

Node.Js:

var express = require("express");

var MongoClient = require('mongodb').MongoClient;

var app = express();

//设置模板引擎

app.set("view engine","ejs");

//数据库连接的地址,最后的斜杠后面表示数据库名字

var shujukuURL = 'mongodb://localhost:27017/itcast';

app.get("/",res){

//先连接数据库,对数据库的所有操作,都要写在他的回调函数里面。

MongoClient.connect(shujukuURL,db) {

if(err){

res.write("数据库连接失败");

return;

}

//查询数据库,遍历所有数据到docs

db.collection('teacher').find({}).toArray(function(err,docs){

if(err){

res.write("遍历错误");

return;

}

res.render("index",{

"result" : docs

});

db.close();

});

});

});

app.get("/add",res){

res.render("add");

});

app.get("/tijiao",res){

//得到参数

var name = req.query.name;

var age = req.query.age;

var yuwenchengji = req.query.yuwenchengji;

var shuxuechengji = req.query.shuxuechengji;

MongoClient.connect(shujukuURL,db) {

if(err){

console.log("数据库连接失败");

return;

}

//将学生的数据存到数据库中

db.collection("teacher").insertOne({

"name" : name,

"age" : age,

"score" : {

"shuxue" : shuxuechengji,

"yuwen" : yuwenchengji

}

},result){

if(err){

console.log("数据库写入失败");

return;

}

res.send("恭喜,数据已经成功插入");

//关闭数据库

db.close();

});

});

});

app.listen(3000);

结果:


第一次访问http://127.0.0.1:3000/:


MongoDB


添加学生http://127.0.0.1:3000/add,并且填写相关的信息:


MongoDB


这时我们查看数据库:


MongoDB


这时我们再一次查看http://127.0.0.1:3000/会发现:


MongoDB


04—案例02

6封装DAO

开发DAO:J2EE开发人员使用数据访问对象(DAO)设计模式把底层的数据访问逻辑和高层的商务逻辑分开.实现DAO模式能够更加专注于编写数据访问代码.


使用我们自己的DAO模块,来实现数据库插入。代码变得简单。

我们这里把常用的增删改查,都封装成为module。(将API进行了简单的封装)


目录结构:


MongoDB


db.js就是我们要封装的js:


(下面的查找中包含了分页和总数,可以在7中查看)

//这个模块里面封装了所有对数据库的常用操作

var MongoClient = require('mongodb').MongoClient;

var settings = require("../settings.js");

//不管数据库什么操作,都是先连接数据库,所以我们可以把连接数据库

//封装成为内部函数

function _connectDB(callback) {

var url = settings.dburl; //从settings文件中,都数据库地址

//连接数据库

MongoClient.connect(url,function (err,db) {

if (err) {

callback(err,null);

return;

}

callback(err,db);

});

}

//插入数据

exports.insertOne = function (collectionName,json,callback) {

_connectDB(function (err,db) {

db.collection(collectionName).insertOne(json,result) {

callback(err,result);

db.close(); //关闭数据库

})

})

};

//查找数据,找到所有数据。args是个对象{"pageamount":10,"page":10}为第3个参数,为了防止有的时候

//可能会不传args而导致的传入的参数只有3个,这时第3个参数不再是args而是callback

exports.find = function (collectionName,C,D) {

if (arguments.length == 3) {

//那么参数C就是callback,参数D没有传。

var callback = C;

var skipnumber = 0;

//数目限制

var limit = 0;

} else if (arguments.length == 4) {

var callback = D;

var args = C;

//应该省略的条数,从第0页开始

var skipnumber = args.pageamount * args.page || 0;

//数目限制

var limit = args.pageamount || 0;

//排序方式

var sort = args.sort || {};

} else {

throw new Error("find函数的参数个数,必须是3个,或者4个。");

return;

}

//连接数据库,连接之后查找所有

_connectDB(function (err,db) {

db.collection(collectionName).find(json).skip(skipnumber).limit(limit).sort(sort).toArray(function(err,docs){

if (err) {

callback(err,null);

db.close(); //关闭数据库

return;

}

callback(null,result);

db.close(); //关闭数据库

})

});

}

//删除

exports.deleteMany = function (collectionName,db) {

//删除

db.collection(collectionName).deleteMany(

json,

function (err,results) {

callback(err,results);

db.close(); //关闭数据库

}

);

});

}

//修改

exports.updateMany = function (collectionName,json1,json2,db) {

db.collection(collectionName).updateMany(

json1,

json2,results);

db.close();

});

})

}

//获得数据的总数

exports.getAllCount = function (collectionName,db) {

db.collection(collectionName).count({}).then(function(count) {

callback(count);

db.close();

});

})

}

Node.js:

var express = require("express");

var app = express();

var db = require("./model/db.js");

//插入数据,使用我们自己封装db模块,就是DAO。

app.get("/charu",res){

//三个参数,往哪个集合中增加,增加什么,增加之后做什么

db.insertOne("teacher",{"name":"小红"},result){

if(err){

console.log("插入失败");

return;

}

res.send("插入成功");

});

});

//查找

app.get("/du",res){

//这个页面现在接受一个page参数。

var page = parseInt(req.query.page); //express中读取get参数很简单

//查找4个参数,在哪个集合查,查什么,分页设置,查完之后做什么

db.find("canguan",{},{"pageamount":6,"page":page},result){

if(err){

console.log(err);

}

res.send(result);

console.log(result.length);

});

});

//删除

app.get("/shan",res){

var borough = req.query.borough;

db.deleteMany("canguan",{"borough":borough},result){

if(err){

console.log(err);

}

res.send(result);

});

});

//修改

app.get("/xiugai",res){

db.updateMany(

"canguan",//集合名字

{

"borough":"Manhattan" //改什么

},

{

$set: { borough: "北京" } //怎么改

},

function(err,result){ //改完之后做什么

if(err){

console.log(err);

}

res.send(result);

}

);

});

app.listen(3000);

05—案例02


更多的可以查看


05—案例03

7将查到的数据分页,数据总数

分页,想想我们的百度百家Ajax案例,当时调用了百度的JSON,有一个参数叫做page=3,生成的JSON不一样。

这个就是分页,就是我们想寻找所有的新闻,但是是位于第3页的新闻。那么有两种做法:


1) 错误的做法: 就是讲所有的result都读取到数组,然后进行数据操作,进行分页;


2) 正确的做法: 就是真的在数据库中,只读取这么多内容。

错误的,我们试图每次都读取全部数据,但是这样开销很大。

var a = [];

db.find("student",result){

for(var i = 10 * page ; i < 10 * (page + 1) ; i++){

a.push(result[i]);

}

res.send(a);

});

所以,mongodb提供了傻傻的两个函数。


limit() 表示找几条数据


skip() 表示基础条数,展示的是skip()基础上的limit()条


MongoDB

假如第一页是page=0。每页10条,所以当前页的查询语句:

db.student.find({}).limit(10).skip(page*10)

数据总数怎么得到?


shell中可以查看:

db.student.stats().count;

05—案例02

8索引index

数据库中,根据一个字段的值,来寻找一个文档,是很常见的操作。比如根据学号来找一个学生。


这个学号,是唯一的,只要有学号,就能唯一确认一个学生的文档。学号这个属性,就非常适合建立索引,这样一来,查找学生就变得简单了。

1.这个语句,能够查看检索的过程:

db.student.find({"name":"user888"});

2.学生的姓名是唯一的,为了快速的进行检索,所以就把name属性建立成为“索引”:

db.student.createIndex({"name":1});

这样,今后通过name寻找student文档的时候,速度非常快。因为能够快速的从索引表中,找到这个文档。


缺点就是插入每条数据的时候,时间变慢了,效率低了。但是换回来的就是寻找的速度快了。

3.索引这个属性对应的属性值,所有的文档都不能相同:

db.members.createIndex( { "user_id": 1 },{ unique: true } );

那么”user_id”不能相同


07—案例shuoshuo

githup地址:https://github.com/haochangdi123/cleanUP-Node.js

意见反馈 常见问题 官方微信 返回顶部