记录用Node.js使用Mongodb中踩过的坑。

MongoDB安装

  • 下载MongoDB
  • 在D盘中创建 mongodb 文件夹然后把下载的包解压后把其中的 bin 文件夹拷贝到创建的 mongodb 文件夹中,
  • 然后在mongodb文件夹中创建一个 data 文件夹,再在 data 文件夹中创建 db 文件夹
  • 打开CMD命令行
    1
    2
    3
    4
    5
    6
    7
    8
    d:
    cd mongodb\bin
    mongod -dbpath D:\mongodb\data\db
    //在打开一个CMD命令行
    d:
    cd mongodb\bin
    mongo
    //这样就可以用了

创建数据库

1
2
3
4
use imooc \创建一个叫chihuo的数据库
db.createCollection(“movies”) \创建一个集合
db.movies.insert({“name”:“admin”,“password”:“111”}) \给movies集合添加一个文档。
db.movies.find() \查询你添加的文档

node.js链接MongoDB

1
2
var mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/imooc')

基本操作

  • 基本命令

    1
    2
    3
    4
    //查看所有数据库
    show dbs
    //查看所有集合
    show tables
  • 插入数据

    1
    2
    3
    4
    //选择imooc数据库
    use imooc
    //向imooc数据库插入数据
    db.movie.insert({x:1,y:1,z:1})
  • 查找数据

    1
    2
    bd.movie.find()
    bd.movie.find({x:1})
  • 更新数据,update只会更新一条数据

    1
    2
    3
    4
    5
    6
    7
    8
    //将{x:1,y:1,z:1},更新为{y:2}
    db.movie.update({x:1},{y:2})
    //更改{x:1,y:1,z:1}中y的数据
    db.movie.update({x:1},{$set:{y:2}})
    //更新一条不存在的数据
    db.movie.update({x:2},{y:2},true)
    //更新多条数据
    db.movie.update({x:1},{$set:{y:2}},false,true)
  • 数据的删除

    1
    2
    3
    4
    //删除表中的数据
    db.movie.remove({x:1})
    //删除表
    db.movie.drop()

索引

  • _id索引

    1
    2
    3
    db.movie.getIndexes()
    //删除索引
    db.movie.dropIndexes()
  • 单键索引

    1
    db.movie.ensureIndex({x:1})
  • 多键索引

    1
    db.movie.insert({x:[1,2,3,4,5]})
  • 复合索引

    1
    db.movie.ensureIndex({x:1,y:2})
  • 过期索引

    1
    db.movie.ensureIndex({x:1},{expireAfterSeconds:10})
    • 必须是指定的时间类型(ISODate,ISODate数组,不能是时间戳否则不能被自动删除)
    • 如果指定了ISODate数组,则按最小的时间进行删除
    • 过期索引不能是复合索引
    • 删除时间是不确定的(后台每60s跑一次,且删除需要时间)
  • 全文索引

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    db.article.ensureIndex({key:"text"})
    db.article.ensureIndex({key_1:"text",key_2:"text"})
    db.article.ensureIndex({"$**":"text"})
    db.article.find({$text:{$search:"coffee"}})
    //或查询
    db.article.find({$text:{$search:"aa bb cc"}})
    //不包含cc
    db.article.find({$text:{$search:"aa bb -cc"}})
    //包含aa bb cc
    db.article.find({$text:{$search:"\"aa\" \"bb"\ \"cc\"}})
    //相似度度查询
    db.article.find({$text:{$search:"aa bb"}},{score:{$meta:"textScore"}})
    db.article.find({$text:{$search:"aa bb"}},{score:{$meta:"textScore"}}).sort({score:{$meta:"textScore"}})
    • 每次查询只能指定一个$text查询
    • $text查询不能出现在$nor查询中
    • 查询中如果包含了$text,hint不再起作用
    • 还不支持中文
  • 地理位置索引

    • 2D索引:平面地理位置索引
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      db.collection.ensureIndex({"w":"2d"})
      //插入:经度:[-180,180] 纬度:[-90,90]
      db.location.insert({[2,3]})
      //返回100个距离最近的点
      db.location.find({w:{near:[1,1]}})
      db.location.find({w:{near:[1,1]},$maxDistance:10})
      //矩形
      db.location.find({w:{geoWithin:{$box:[[1,1],[2,2]]}}})
      //圆
      db.location.find({w:{geoWithin:{$center:[[0,0],5]}}})
      //多边形
      db.location.find({w:{geoWithin:{$polygon:[[0,0],[0,1],[2,1],[3,1]]}}})
      //geoNear
      db.runCommand(
      {
      geoNear:<collecton>,
      near:[x,y],
      minDistance:(对2d索引无效)
      maxDistance:
      num:限制返回数目
      })
      db.runCommand({geoNear:"location",near:[1,2],maxDistance:10,num:1})
  • 索引属性

    • name:db.collection.ensureIndex({},{name:” “})
    • unique:db.collection.ensureIndex({},{unique:true/false})
    • sparse:db.collection.ensureIndex({},{sparse:true/false})
    • expireAfterSecond

mongoose的使用

  • schema

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    var mongoose = require('mongoose')
    var MovieSchema = new mongoose.Schema({
    doctor: String,
    title: String,
    language: String,
    country: String,
    summary: String,
    flash: String,
    poster: String,
    year: String,
    meta:{
    creatAt:{
    tyep:Date,
    default:new Date.now()
    },
    updateAt:{
    type:Date,
    default:new Date.now()
    }
    }
    })
    MovieSchema.pre('save',function(next){
    if(this.isNew){
    this.meta.createAt = this.mata.updateAt = Date.now())
    }else{
    this.meta.createAt =Date.now()
    }
    next()
    })
    MovieSchema.statics = {
    fetch: function(cb){
    return this
    .find({})
    .sort('meta.updateAt')
    .exec(cb)
    },
    findById: function(id,cb){
    return this
    .findOne({_id: id})
    .exec(cb)
    }
    }
    module.exports = MovieSchma
  • model

    1
    2
    3
    4
    5
    var mongoose = require('mongoose')
    var MovieSchema = require('../schemas/movies')
    var Movie = mongoose.model('Movie',MovieSchema)
    module.exports = Movie
  • 使用

    1
    2
    3
    4
    5
    6
    7
    var Movie = require('./models/movie')
    Movie.findById(id,function (err,movie) {
    res.render('admin',{
    title: '电影后台更新页',
    movie:movie
    })
    })

模块的使用

1
2
3
4
5
6
7
8
9
10
11
12
var _ = require('underscore')
// underscore用新对象替换旧对象
_movie = _.extend(movie,movieObj)
var bodyParser = require('body-parser')
// 格式化时间
app.locals.moment =require('moment')
//jade中使用
#{moment(item.meta.createdAt).format('YYYY/MM/DD')}
// 提交表单 数据格式化
app.use(bodyParser.urlencoded({ extended: true }))
// 静态资源目录 /表示public目录下
app.use(express.static(path.join(__dirname,'public')))

密码加密

1
2
3
4
5
6
7
8
9
10
11
var bcrypt = require('bcryptjs')
bcrypt.genSalt(SALT_WORK_FACTOR, function(err, salt) {
if (err) return next(err)
bcrypt.hash(user.password, salt, function(err, hash) {
if (err) return next(err)
user.password = hash
next()
})
})