node.js MongoDB简单使用(Express服务器)

一、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  进程
关闭.png

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

创建ExpressAPP.jpg

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


user.server.model.png
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.png

安装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();
  }
});
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容