简介:

  • 传统关系类型(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. 后台返回json数据,前台显示代码

    List list = "从DAL获取的数据集合" //取出分页标签html int pageIndex = context.Request["pageIndex&quo ...

  2. Y2K Accounting Bug(贪心)

    Y2K Accounting Bug Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10945   Accepted: 54 ...

  3. Poj 3233 Matrix Power Series(矩阵二分快速幂)

    题目链接:http://poj.org/problem?id=3233 解题报告:输入一个边长为n的矩阵A,然后输入一个k,要你求A + A^2 + A^3 + A^4 + A^5.......A^k ...

  4. SQL注入--宽字节注入

    PHP测试代码: <?php // 面向对象写法 $id=addslashes($_GET[‘id’]); //获取id并转义预定义字符 // /$id=$_GET[‘id’]; $mysqli ...

  5. 跟着百度学PHP[1]-if条件嵌套

    权当自己的学习笔记.望大牛们切勿参考.如若发现错误,万望指出!  慕课任务 假设在发工资的时候,不仅判定性别,还要判定男性是否有房,没有房,可以发放住房补贴,对于女性,判定是否怀孕,怀孕还有怀孕补贴. ...

  6. bwa的使用方法

    bwa的使用需要两中输入文件:    Reference genome data(fasta格式 .fa, .fasta, .fna)    Short reads data (fastaq格式 .f ...

  7. iOS 如何使用自定义字体

    首先,你需要有字体文件,比如 xxx.otf,之后你需要到工程的info配置文件中加入Fonts provided by application的值,如下图 之后,就可以使用字体名和UIFont的方法 ...

  8. Java for LeetCode 064 Minimum Path Sum

    Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which ...

  9. 【JAVA、C++】LeetCode 015 3Sum

    Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all un ...

  10. MFC基于Dialog的工程中使用OSG

    osg的例子有osgviewerMFC,是MDI类型的MFC工程,我一般用基于对话框的MFC较多. 注意观察MFC_OSG.h文件中的cOSG构造函数,参数是一个窗口句柄hWnd,这里的窗口可以不只局 ...