一、MongoDB介绍
MongoDB是Nosql数据库,NoSQL(NoSQL = Not Only SQL ),意即"不仅仅是SQL"。也有人叫文档数据库,这类数据库没有表和行的概念,只有类似含义的集合和文档,集合与关系数据库的表类似,文档与关系数据库的行类似。
MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。
MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。
特点
- 使用BSON存储数据
二进制的json,相对于json,Bson在性能和空间占用上有一定的优势,可以非常方便用它来进行键值对的存储 - 支持相对丰富的查询操作
- 支持索引
查询时,如果发现需要检索的字段已经建立了索引,就不用扫描整个集合,只需要在索引中进行查询,进而获取文档的ID,并通过id获取整个文档 - 副本集
MongoDB支持多个实例,或者说多个服务器运行同一个数据库,其中一个叫活跃节点,其他的叫备份节点,这个便是MongoDB的副本集,副本集不仅能提升服务器应对硬件故障的能力,还能提升数据库的读取性能。副本集还有一种自治和推举功能,会根据网络情况对活跃节点进行调整。 - 分片
当数据库数据不断增加时,可以通过分片功能将数据存储到不同服务器上,每个服务器都有一个数据库,而所有的分片合在一起,便组成了一个大的数据库,这样便能实现数据库的水平扩展。 - 无模式
同一个集合之内的文档数据结构有可能不一样,甚至可以毫不相关,这便是MongoDB的无模式特性。 - 部署简单方便
有优点也有缺点,会带来安全问题,MongoDB默认是没有实名验证的,所以如果不做相应的配置,而防火墙有没有设置相应的规则,那么任何人便可以访问你的数据库
二、 服务启动
MongoDB运行的两种方式
- 以守护进程的方式运行,一般它名为mongoD,D是daemon的意思
- MongoD还可以在当前会话的前台运行
当一个MongoDB的数据库启动之后,可以将这个服务称之为MongoDB的实例
查看系统是否启用mongod服务,并制定MongoD数据目录
[root@localhost db]# which mongod
/usr/bin/mongod
[root@localhost db]# mkdir -p /data/db
[root@localhost db]# df lh
df: ‘lh’: No such file or directory
[root@localhost db]# df -lh
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/centos-root 6.2G 2.2G 4.1G 36% /
devtmpfs 485M 0 485M 0% /dev
tmpfs 496M 0 496M 0% /dev/shm
tmpfs 496M 6.8M 490M 2% /run
tmpfs 496M 0 496M 0% /sys/fs/cgroup
/dev/sda1 1014M 132M 883M 13% /boot
tmpfs 100M 0 100M 0% /run/user/0
[root@localhost db]# mongod --dbpath=/data/db --port=27017
在当前会话启动Mongo
[root@localhost db]# mongo
MongoDB shell version: 2.6.12
connecting to: test
Server has startup warnings:
2018-10-25T22:29:03.696-0400 [initandlisten]
2018-10-25T22:29:03.696-0400 [initandlisten] ** WARNING: Readahead for /data/db is set to 4096KB
2018-10-25T22:29:03.696-0400 [initandlisten] ** We suggest setting it to 256KB (512 sectors) or less
2018-10-25T22:29:03.696-0400 [initandlisten] ** http://dochub.mongodb.org/core/readahead
>
以守护进程的方式启动
[root@localhost db]# mongod --dbpath=/data/db --port=27017 --fork --logpath=/var/log/mongd.log
logpath:设置日志目录
后台启动两种关闭的方法
mongod --shutdown
kill 进程
MongoD客户端的使用
使用xshell连接服务器,
[root@localhost ~]# mongo
MongoDB shell version: 2.6.12
connecting to: test
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
http://docs.mongodb.org/
Questions? Try the support group
http://groups.google.com/group/mongodb-user
Server has startup warnings:
2018-10-25T22:29:03.696-0400 [initandlisten]
2018-10-25T22:29:03.696-0400 [initandlisten] ** WARNING: Readahead for /data/db is set to 4096KB
2018-10-25T22:29:03.696-0400 [initandlisten] ** We suggest setting it to 256KB (512 sectors) or less
2018-10-25T22:29:03.696-0400 [initandlisten] ** http://dochub.mongodb.org/core/readahead
> show dbs // 显示数据库列表
admin (empty)
local 0.078GB
> use testDb1 //当创建一个集合(table)的时候会自动创建当前数据库
switched to db testDb1
> show dbs
admin (empty)
local 0.078GB
> db.users.insert({"username":"zhang"}); // 插入数据
WriteResult({ "nInserted" : 1 })
> show dbs
admin (empty)
local 0.078GB
testDb1 0.078GB
> show collections // 显示集合列表
system.indexes
users
> db.users.find() // 查找
{ "_id" : ObjectId("5bd27d1dc2988faea8124add"), "username" : "zhang" }
> db.users.insert({"username":"huang", "group":"Smit"});
WriteResult({ "nInserted" : 1 })
> db.users.find()
{ "_id" : ObjectId("5bd27d1dc2988faea8124add"), "username" : "zhang" }
{ "_id" : ObjectId("5bd27e43c2988faea8124ade"), "username" : "huang", "group" : "Smit" }
> db.users.find().count()
2
> db.users.insert({"username":"huang", "group":"Smile"});
WriteResult({ "nInserted" : 1 })
> db.users.find()
{ "_id" : ObjectId("5bd27d1dc2988faea8124add"), "username" : "zhang" }
{ "_id" : ObjectId("5bd27e43c2988faea8124ade"), "username" : "huang", "group" : "Smit" }
{ "_id" : ObjectId("5bd27ec1c2988faea8124adf"), "username" : "huang", "group" : "Smile" }
> db.users.find({"_id":ObjectId("5bd27d1dc2988faea8124add")}); // 条件查找
{ "_id" : ObjectId("5bd27d1dc2988faea8124add"), "username" : "zhang" }
> db.users.update({"username":"huang"}, {$set:{"group":"Albaba"}});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.users.find();
{ "_id" : ObjectId("5bd27d1dc2988faea8124add"), "username" : "zhang" }
{ "_id" : ObjectId("5bd27e43c2988faea8124ade"), "username" : "huang", "group" : "Albaba" }
{ "_id" : ObjectId("5bd27ec1c2988faea8124adf"), "username" : "huang", "group" : "Smile" }
> db.users.update({"username":"huang"}, {$set:{"group":"Baidu"}},{multi:true}); // 更新数据
WriteResult({ "nMatched" : 2, "nUpserted" : 0, "nModified" : 2 })
> db.users.find();
{ "_id" : ObjectId("5bd27d1dc2988faea8124add"), "username" : "zhang" }
{ "_id" : ObjectId("5bd27e43c2988faea8124ade"), "username" : "huang", "group" : "Baidu" }
{ "_id" : ObjectId("5bd27ec1c2988faea8124adf"), "username" : "huang", "group" : "Baidu" }
> db.users.save({"_id":ObjectId("5bd27ec1c2988faea8124adf"), "group":"BYD"}); // 另一种更新数据的方法
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.users.find();
{ "_id" : ObjectId("5bd27d1dc2988faea8124add"), "username" : "zhang" }
{ "_id" : ObjectId("5bd27e43c2988faea8124ade"), "username" : "huang", "group" : "Baidu" }
{ "_id" : ObjectId("5bd27ec1c2988faea8124adf"), "group" : "BYD" }
> db.users.insert({"group":"MD"});
WriteResult({ "nInserted" : 1 })
> db.users.insert({"group":"MD"});
WriteResult({ "nInserted" : 1 })
> db.users.find();
{ "_id" : ObjectId("5bd27d1dc2988faea8124add"), "username" : "zhang" }
{ "_id" : ObjectId("5bd27e43c2988faea8124ade"), "username" : "huang", "group" : "Baidu" }
{ "_id" : ObjectId("5bd27ec1c2988faea8124adf"), "group" : "BYD" }
{ "_id" : ObjectId("5bd28789c2988faea8124ae0"), "group" : "MD" }
{ "_id" : ObjectId("5bd2878dc2988faea8124ae1"), "group" : "MD" }
> db.users.remove({"group":"MD"}); // 删除
WriteResult({ "nRemoved" : 2 })
> db.users.find();
{ "_id" : ObjectId("5bd27d1dc2988faea8124add"), "username" : "zhang" }
{ "_id" : ObjectId("5bd27e43c2988faea8124ade"), "username" : "huang", "group" : "Baidu" }
{ "_id" : ObjectId("5bd27ec1c2988faea8124adf"), "group" : "BYD" }
> db.users.remove({"group":"MD"});
WriteResult({ "nRemoved" : 0 })
> db.users.insert({"group":"MD"});
WriteResult({ "nInserted" : 1 })
> db.users.insert({"group":"MD"});
WriteResult({ "nInserted" : 1 })
> db.users.find();
{ "_id" : ObjectId("5bd27d1dc2988faea8124add"), "username" : "zhang" }
{ "_id" : ObjectId("5bd27e43c2988faea8124ade"), "username" : "huang", "group" : "Baidu" }
{ "_id" : ObjectId("5bd27ec1c2988faea8124adf"), "group" : "BYD" }
{ "_id" : ObjectId("5bd287dac2988faea8124ae2"), "group" : "MD" }
{ "_id" : ObjectId("5bd287dcc2988faea8124ae3"), "group" : "MD" }
> db.users.remove({"group":"MD"}, true); // 删除单个
WriteResult({ "nRemoved" : 1 })
> db.users.find();
{ "_id" : ObjectId("5bd27d1dc2988faea8124add"), "username" : "zhang" }
{ "_id" : ObjectId("5bd27e43c2988faea8124ade"), "username" : "huang", "group" : "Baidu" }
{ "_id" : ObjectId("5bd27ec1c2988faea8124adf"), "group" : "BYD" }
{ "_id" : ObjectId("5bd287dcc2988faea8124ae3"), "group" : "MD" }
> db.users.remove(); //删除所有
2018-10-25T23:20:47.918-0400 remove needs a query at src/mongo/shell/collection.js:299
> db.user.find();
>
三、在Express项目中使用MongoDB
1、创建express APP
2、存储数据库相关的配置
创建config文件夹
创建配置文件config.js,导出MongoDB uri连接数据的方法
标准 URI 连接语法:
mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]
mongodb:// 这是固定的格式,必须要指定。
username:password@ 可选项,如果设置,在连接数据库服务器之后,驱动都会尝试登陆这个数据库
host1 必须的指定至少一个host, host1 是这个URI唯一要填写的。它指定了要连接服务器的地址。如果要连接复制集,请指定多个主机地址。
portX 可选的指定端口,如果不填,默认为27017
/database 如果指定username:password@,连接并验证登陆指定数据库。若不指定,默认打开 test 数据库。
?options 是连接选项。如果不使用/database,则前面需要加上/。所有连接选项都是键值对name=value,键值对之间通过&或;(分号)隔开
module.exports = {
mongodb: "mongodb://127.0.0.1:27017/testDb1"
};
在config文件夹创建MongoDB的配置文件mongoose.js
使用mongoose来操作MongoDB
var mongoose = require('mongoose');
var config = require('./config.js');
module.exports = function () {
var db = mongoose.connect(config.mongodb,{useNewUrlParser:true},function (err) {
if (err) {
console.log("Connection Error:" +err);
} else {
console.log("Connection success!");
}
}); // 连接数据库
require('../models/user.server.model.js');
return db;
};
接下来我们要怎样组织model和Schema?
把mongoose的model组织到专门的文件夹里面
创建models文件夹
User.server.model.js
User:说明是什么的model,user的model
Server:表示服务端的一个model
var mongoose = require('mongoose');
var UserSchema = new mongoose.Schema({
uid: Number,
username: String,
createTime: Date,
loastLogin: Date
});
mongoose.model('User', UserSchema); // 注册model
怎么样让mongoose配置加入到应用中来,
打开app.js,道路mongoose的配置文件
var mongoose = require('./config/mongoose.js');
var db = mongoose();
安装mongoose
cnpm install mongoose --save
在routes目录下的users.js中增加Mongoose相关的路由
var express = require('express');
var router = express.Router();
var mongoose = require('mongoose');
var User = mongoose.model('User');
/* GET users listing. */
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});
router.get('/test', function (req, res, next) {
var user = new User({
uid: 1,
username: 'Smit'
});
user.save(function (err) {
if (err) {
res.end('Error');
return next();
}
User.find({},function (err, docs) {
if(err) {
res.end('Error');
return next();
}
res.json(docs);
});
})
});
module.exports = router;
把项目同步到后台,运行项目测试如下:
[root@localhost ~]# curl -get http://127.0.0.1:3000/users/test
[{"_id":"5bd90cbcb36ec7017e9ff296","username":"zhang"},{"_id":"5bda6a3d1e37d605ae2b87f1","uid":1,"username":"Smit","__v":0}]
可以看到数据已经成功写入到了数据库中!
补充
这里在补充在nodejs中mongoose对数据的其他操作:
1、建立模型
var BookSchema = new mongoose.Schema({
name: String,
author: String,
publishTime: Date
});
2、查找
mongoose.model('Book', BookSchema);
var mongoose = require('mongoose');
require('./model.js');
var Book = mongoose.model('Book');
Book.find({}, function(err, docs){
if(err) {
console.log('err:', err);
return;
}
console.log('result:', docs);
});
3、查找特定数据
var mongoose = require('mongoose');
require('./model.js');
var Book = mongoose.model('Book');
// 请务必注意, find 和 findOne 得到的结果是不一样的,前者是一个数组,后者直接是一个对象
Book.findOne({author:"Jim"}, function(err, doc){
if(err) {
console.log('err:', err);
return;
}
doc.author = 'Jame';
doc.save();
console.log('findOne result: ', doc);
});
4、保存一组数据到数据库
var mongoose = require('mongoose');
require('./model.js');
var Book = mongoose.model('Book');
var book = new Book({
name: "MEAN Web Development",
author: "Green",
publishTime: new Date()
});
book.author = 'Jim';
book.save(function(err){
console.log('save status:', err ? 'failed' : 'success');
});
5、集合操作
var mongoose = require('mongoose');
require('./model.js');
var Book = mongoose.model('Book');
var cond = {
// 还可以使用 $and
$or: [
// 除了值相当,还有大于 $gt ,大于等于 $gte ,小于 $lt ,小于等于 $lte,不等于 $ne
{author: 'Jame'},
{author: 'Jim'}
]
};
Book.find(cond, function(err, docs){
if(err) {
console.log('find by cond err:', err)
return;
}
console.log('cond:', cond,'result:', docs);
});
6、查找特定数据并删除
var mongoose = require('mongoose');
require('./model.js');
var Book = mongoose.model('Book');
Book.findOne({author: 'Jim'}, function(err, doc){
if(err){
console.log('findOne err:', err);
return;
}
if(doc) {
// remove() 也是有回调函数的,可以判断是否删除成功
doc.remove();
}
});