简介:

  • 传统关系类型(ORM:Object-Relational Mapper),MongoDB(ODM:Object Document Mapper);
  • MongoDB是一个面向文档,schme无关(可以将任意类型的文档数据存储到集合中)的数据库;
  • MongoDB中可以将数据都看作文档,文档可以是任意深度的;
  • 当有数据存储后,这些文档会以十分接近JSON格式的形式存储;
  • 文档数据的数据类型可以是混合的,Node.js获取储存文档数据后,其类型和储存时候的类型是一样的;

例子:

  • package.json:

    {
    "name": "user-auth-example",
    "version": "0.0.1",
    "dependencies": {
    "express": "2.5.8",
    "mongodb": "1.3.19",
    "jade": "0.20.3"
    }
    }
  • 使用jade:  //缩进,默认两个空格 ; //注意tab和space不要混着用

    • views/layout.jade:

      doctype 5
      html
      head
      title MongoDB example
      body
      h1 My first MongoDB app
      hr
      block body
    • views/index.jade:
      extends layout
      block body
      if (authenticated)
      p Welcome back, #{me.email}
      a(href="/logout") Logout
      else
      p Welcome new visitor!
      ul
      li: a(href="/login") Login
      li: a(href="/signup") Signup
    • views/login.jade:
      extends layout
      block body
      form(action="/login", method="POST")
      fieldset
      legend Log in
      if (signupEmail)
      #{signupEmail}
      p Congratulations on signing up! Please login below
      p
      label Email
      input(name="user[email]", type="text", value=signupEmail)
      p
      label Password
      input(name="user[password]", type="password")
      p
      button submit
      p
      a(href="/") Go back
    • views/signup.jade:
      extends layout
      block body
      form(action="/signup", method="POST")
      fieldset
      legend Sign up
      p
      label First
      input(name="user[first]", type="text")
      p
      label Last
      input(name="user[last]", type="text")
      p
      label Email
      input(name="user[email]", type="text")
      p
      label Password
      input(name="user[password]", type="password")
      p
      button Submit
      p
      a(href="/") Go back
  • server.js:
    var express = require('express');
    var mongodb = require('mongodb');
    var ObjectId = mongodb.ObjectID; var app = express.createServer(); //加入中间件
    app.use(express.bodyParser());
    app.use(express.cookieParser());
    app.use(express.session({secret: 'my secret'}));
    app.use(function(req, res, next) { //身份验证中间件
    if (req.session.loggedIn) {
    res.local('authenticated', true); //express 的res.local API
    app.users.findOne({"_id": ObjectId(req.session.loggedIn)}, function(err, doc) {
    if (err) return next(err);
    res.local('me', doc);
    next()
    })
    } else {
    res.local('authenticated', false);
    next()
    }
    }); app.set('view engine', 'jade');
    //express 3不需要这段代码
    app.set('view options', {layout: false}); //创建mongodb.Server 初始化服务器
    var server = new mongodb.Server('127.0.0.1', 27017); //告诉驱动器连接数据库'my-website',不存在会创建
    new mongodb.Db('my-website', server, {w: 1}).open(function(err, client) {
    if (err) {
    throw err
    }
    console.log('\033[96m + \033[39m connected to mongodb'); //创建数据库操作集合的快捷方式
    app.users = new mongodb.Collection(client, 'users');
    // 不管索引是否存在,都可以调用这个命令来确保在查询前建立了索引
    client.ensureIndex('users', 'email', function(err) {
    if (err) throw err
    client.ensureIndex('users', 'password', function() {
    if (err) throw err
    });
    console.log('\033[96m + \033[39m ensured indexes');
    app.listen(3000, function() {
    console.log('\033[96m + \033[39m app listening on *:3000');
    })
    })
    }); app.get('/', function(req, res) {
    res.render('index')
    });
    app.get('/login', function(req, res) {
    if (req.session.loggedIn) {
    res.redirect('/');
    } else {
    res.render('login', {signupEmail: ''});
    }
    });
    app.get('/login/:signupEmail', function(req, res) {
    res.render('login', {signupEmail: req.params.signupEmail});
    });
    app.post('/login', function(req, res) {
    //文档查找
    app.users.findOne({email: req.body.user.email, password: req.body.user.password}, function(err, doc) {
    if (err) return next(err)
    if (!doc) return res.send('User not found. Go back and try again');
    req.session.loggedIn = doc._id.toString();
    res.redirect('/');
    })
    });
    app.get('/logout', function(req, res) {
    req.session.loggedIn = null
    res.redirect('/');
    });
    app.get('/signup', function(req, res) {
    res.render('signup');
    });
    app.post('/signup', function(req, res, next) {
    //创建文档
    app.users.insert(req.body.user, function(err, doc) {
    if (err) {
    return next(err)
    }
    res.redirect('/login/' + doc[0].email);
    })
    });

问题:

  • 校验://表单校验类型,大小等; mongoose通过在应用层定义scheme(模型)来解决;
  • 原子性://多个用户同时对同一文档进行了操作; mongoose通过检查要对文档做的修改,并只修改受影响的字段来解决;
  • 安全模式:在使用驱动时,对文档的操作中有一个可选参数: app.users.insert({},{<options>});其中safe选项对在对数据库进行修改时启动安全模式;默认情况下,在操作完成后,如果有错误发生,MongoDB不会及时通知;驱动器需要早操作后调用db.getLastError,来验证数据修改是否成功; mongoose默认会对所有操作启用安全模式;

Mongoose://mongoose假定绝大部分应用程序都是用一个数据库;使用mongoose的时候无需关系连接是否建立,它会把数据库操作指令缓存起来,在连上数据库后发送出去;

  • 定义模型:类型包括Date,String,Number,Array,Object,ObjectId(MongiDB提供);例子:

    var Schema = mongoose.Schema;
    var ObjectId = Schema.ObjectId; //创建模型
    var PostSchema = new Schema({
    author : ObjectId,
    title: {type : String, default: 'default' }, //选项格式
    body : String,
    date : Date
    }); //注册模型 var Post = mongoose.model("BlogPost', PostSchema); //获取模型
    var Post = mongoose.modek('BlogPost'); //操作模型:创建 new Post({title: “My Title"}).save(function (err) {
    ....
    });  
  • 定义嵌套的键:
    var BlogPost = new Schema({
    title : String,
    meta : {
    votes : Number,
    favs : Number
    }
    });
    //特定查找
    db.blogposts.find({'meta.votes':5});
  • 定义嵌套的文档:
    var Comments = new Schema({......});
    var BlogPost = new Schema({
    .....
    comments : [Comments],
    .....
    });
  • 构建索引:要对指定的键做索引,需要传递一个index选项,并将值设置为true;
    //设置title键做索引,并将uid键设置为唯一;
    
    var BlogPost = new Schema({
    author : ObjectId,
    title : {type: String, index : true},
    uid : {type : Number, unique : true}
    })
  • 中间件:有时候会在不同的地方以不同的方式对同样的数据进行修改,通过模型接口对这部分对数据库的交互集中避免代码重复;
    //定义一操作在特定动作前执行,如在删除博文时发送电子邮件给作者;
    Blogpost.prev('remove', function (next) {
    emailAuthor(this.email, 'Blog post removed!');
    next();
    });
  • 探测模型状态:根据要对当前模型做的不同更改进行不同操作
    Blogpost.prev('save', function(next) {
    if(this.isNew) {
    ....
    } else {
    .....
    }
    });
  • 查询:
    • find
    • findOne
    • findById //根据ObjectId
    • remove
    • update
    • count
  • 扩展查询:如果对某个查询不提供回调函数,那么直到调用run才会执行;
    Post.find({autor: '...'})
    .where('title','My title')
    .sort('content', -1)
    .limit(5)
    .run(function(err, post) {
    ...............
    })
  • 排序:
    query.sort('key', 1);
    query.sort('some.key',-1);
  • 选择:若文档大,只想要指定部分;
    Post.find().select('field', 'field2');
  • 限制:现在查询结果的数量;
    query.limit(5);
  • 跳过:跳过指定数量的文档数据
    query.skip(10);
  • 自动产生键:
    //查询一个博文的时候,还获取对应的作者;为ObjectId类型提供一个href属性;
    var BlogPost = new Schema({
    author : {type : ObjectId, ref : 'Author'},
    title : String,
    body : String,
    meta : {
    votes : Number,
    favs : Number
    }
    }) //对指定键调用populate就可自动生成;
    BlogPost.find({title : 'My title'})
    .populate('author')
    .run(function (err, doc) {
    console.log(doc.ahthor.email);
    });
  • 对上一个server.js使用mongoose之后:
    var express =  require('express');
    var mongoose = require('mongoose'); //建立模型
    var Schema = mongoose.Schema;
    var User = mongoose.model('User', new Schema({
    first: String,
    last: String,
    email: {type: String, unique: true},
    password: {type: String, index: true}
    })); var app = express.createServer(
    express.bodyParser(),express.cookieParser(),express.session({secret: 'my secret'})
    ); app.use(function(req, res, next) {
    if (req.session.loggedIn) {
    res.local('authenticated', true);
    User.findById(req.session.loggedIn, function(err, doc) {
    if (err) return next(err);
    res.local('me', doc);
    next();
    });
    } else {
    res.local('authenticated', false);
    next();
    }
    }); app.set('view engine', 'jade');
    app.set('view options', {layout: false}); app.get('/', function(req, res) {
    res.render('index')
    }); app.get('/login', function(req, res) {
    if (req.session.loggedIn) {
    res.redirect('/');
    } else {
    res.render('login', {signupEmail: ''});
    }
    }); app.get('/login/:signupEmail', function(req, res) {
    res.render('login', {signupEmail: req.params.signupEmail});
    }); app.post('/login', function(req, res) {
    //文档查找
    User.findOne({email: req.body.user.email, password: req.body.user.password}, function(err, doc) {
    if (err) return next(err)
    if (!doc) return res.send('User not found. Go back and try again');
    req.session.loggedIn = doc._id.toString();
    res.redirect('/');
    })
    }); app.get('/logout', function(req, res) {
    req.session.loggedIn = null
    res.redirect('/')
    }); app.get('/signup', function(req, res) {
    res.render('signup')
    }); app.post('/signup', function(req, res, next) {
    var user = new User(req.body.user);
    user.save(function(err) {
    if (err) return next(err);
    res.redirect('/login/' + user.email);
    });
    }); //连接数据库
    mongoose.connect('mongodb://127.0.0.1/my-website');
    app.listen(3000, function() {
    console.log('\033[96m + \033[39m app listening on *: 3000');
    });

 

node连接--MongoDB的更多相关文章

  1. 使用node连接MongoDB数据 综本地及linux服务器记

    gitee地址 启动mongo D:\MongoDB> ./bin/mongod --dbpath ./data/db MongoDB 提供了简单的 HTTP 用户界面. 如果你想启用该功能,需 ...

  2. node连接mongoDB篇

    一般介绍: 由于mongodb数据库在javascript脚本环境中支持bson对象(json对象的二进制形式)的存取,因此对于数据的存取的效率是非常高的.在mongodb数据库中,将每一条等待插入的 ...

  3. node连接mongodb(简略版)

    1.先通过配置启动mongodb,然后新建db.js     已经对相对应的数据库操作增删改查封装完成. //这个模块里面封装了所有对数据库的常用操作 var MongoClient = requir ...

  4. 跟我一起用node-express搭建一个小项目(node连接mongodb)[三]

    数据库虽然安装并启动成功了,但我们需要连接数据库后才能使用数据库. 怎么才能在 Node.js 中使用 MongoDB 呢? 我们使用官方提供的 node-mongodb-native 驱动模块,打开 ...

  5. 【node】node连接mongodb操作数据库

    1.下载第三方模块mongodb cnpm install mongodb --save 2.检测是否连接成功 1.引入第三方模块mongodb并创建一个客户端 const MongoClient = ...

  6. 【node】------node连接mongodb操作数据库------【巷子】

    1.下载第三方模块mongodb cnpm install mongodb --save 2.检测是否连接成功 1.引入第三方模块mongodb并创建一个客户端 const MongoClient = ...

  7. 【Node.js】二、基于Express框架 + 连接MongoDB + 写后端接口

    在上节,我们讲了如何搭建express环境,现在我们说说如何通过node.js写服务接口给前端调用 1. 首先通过MongoDB建好数据库与表格 例如,我的数据库名字为db_demo,数据库表格为go ...

  8. 初学node.js-nodejs连接MongoDB(5)

    一.吧MongoDB的驱动程序添加到Node.js中 Node.js 连接 MongoDB 连接

  9. docker node项目 连接mongodb

    在弄docker部署node项目的时候遇到了连接mongdb的问题,记录一下问题解决办法 一.Docker 安装 MongoDB 1.查找Docker Hub上的mongo镜像 [root@VM_49 ...

随机推荐

  1. C语言中全局变量、局部变量、静态全局变量、静态局部变量的区别 (转)

    1.C++变量根据定义的位置的不同的生命周期,具有不同的作用域,作用域可分为6种: 全局作用域,局部作用域,语句作用域,类作用域,命名空间作用域和文件作用域. 从作用域看: 1>全局变量具有全局 ...

  2. java工具类包

    Hutool 提供丰富的java方法,其maven引用 <dependency> <groupId>com.xiaoleilu</groupId> <arti ...

  3. U盘安装Linux安装报错及解决方案

    导读 从网上看到了<Linux就该这么学>后,偏离软件行业多年的我下定决心回归!这篇文章是我这一个小白的亲身经历,希望能被采纳! 开始按照<Linux就该这么学>中所讲在自己的 ...

  4. JSONKit 简单使用

    http://blog.csdn.net/l_ch_g/article/details/8477187 例子上写的比较浅显易懂, 不过我还是稍微总结一下: 导入JSONKit.h之后 字符串转NSDi ...

  5. Clustering by fast search and find of density peaks

    参考:http://www.52ml.net/16296.html 这个算法的优点就在于,它首先一步就能找到聚类中心,然后划分类别.而其他算法需要反复迭代才能找到中心聚类. 就是不知道代码该怎么写.. ...

  6. python如何安装pip和easy_installer工具

    1.在以下地址下载最新的PIP安装文件:http://pypi.python.org/pypi/pip#downloads 2.解压安装 3.下载Windows的easy installer,然后安装 ...

  7. DCMTK354之VC++ 2008 MFC应用程序配置完整过程

    花了一个礼拜,终于在VC++2008 MFC 应用程序中完成了首个基于DCMTK354的首个程序ECHOSCUWIN32,现将过程记录下来,便于日后查阅,同时也提供给那些有幸看到此博文而对他们又有帮助 ...

  8. 阿里云vps上mysql挂掉的解决办法

    阿里云vps上mysql挂掉的解决办法 4条回复 用阿里云的vps用作blog服务器,系统很稳定,已经100多天一直运行正常,大概从上个月开始发现blog的mysql会有时挂掉,会收到短信通知.之前没 ...

  9. php远程抓取网站图片并保存

    以前看到网上别人说写程序抓取网页图片的,感觉挺神奇,心想什么时候我自己也写一个抓取图片的方法! 刚好这两天没什么事,就参考了网上一个php抓取图片代码,重点借鉴了 匹配img标签和其src属性正则的写 ...

  10. Resumable uploads over HTTP. Protocol specification

    Valery Kholodkov <valery@grid.net.ru>, 2010 1. Introduction This document describes applicatio ...