MongoDB 学习(三)

初学 MongoDB !

一、高级操作

1. 聚合aggregate

  • 聚合(aggregate)主要用于计算数据
  • 语法:

    1
    db.集合名称.aggregate([{管道:{表达式}}])
  • 管道

    • 在mongodb中,文档处理完毕后,通过管道进行下一次处理
    • $group:将集合中的文档分组,可用于统计结果
    • $match:过滤数据,只输出符合条件的文档
    • $project:修改输入文档的结构,如重命名、增加、删除字段、创建计算结果
    • $sort:将输入文档排序后输出
    • $limit:限制聚合管道返回的文档数
    • $skip:跳过指定数量的文档,并返回余下的文档
    • $unwind:讲数组类型的文档进行拆分
  • 表达式

    • 处理输入文档并输出
    • 语法:

      1
      表达式:'$列名'
    • 常用表达式

      • $sum:计算总和,$sum:1同count表示计数
      • $avg:计算平均值
      • $min:获取最小值
      • $max:获取最大值
      • $push:在结果文档中插入一个值到一个数组中
      • $first:根据资源文档的排序获取第一个文档数据
      • $last:根据资源文档的排序获取最后一个文档数据

2. $group

  • 将集合中的文档分组,可用于统计结果
  • 将_id表述分组的依据,使用某个字段的格式为’$字段’
  • 例一:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    -- 统计男生、女生的总人数
    db.集合名称.aggregate([
    {
    $group:{
    _id:'$gender',
    counter:{$sum:1}
    }
    }
    ])
  • Group by null

    • 将集合中所有文档分为一组
    • 例一:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      -- 求学生总人数、平均年龄
      db.集合名称.aggregate([
      {$group:
      {
      _id:null,
      counter:{$sum:1},
      avgAge:{$avg:'$age'}
      }
      }
      ])
  • 透视数据

    • 例一:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      -- 统计学生性别及学生姓名
      db.集合名称.aggregate([
      {$group:
      {
      _id:'$gender',
      name:{$push:'$name'}
      }
      }
      ])
  • 使用$$ROOT可以将文档内容加入到结果集的数组中,代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    db.集合名称.aggregate([
    {$group:
    {
    _id:'$gender',
    name:{$push:'$$ROOT'}
    }
    }
    ])

3. $match

  • 用于过滤数据,只输出符合条件的文档
  • 使用MongoDB的标准查询操作
  • 例一:

    1
    2
    3
    4
    5
    -- 查询年龄大于20的学生
    db.集合名称.aggregate([
    {$match:{age:{$gt:20}}
    }
    ])
  • 例二:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    -- 查询年龄大于20的男生、女生人数
    db.集合名称.aggregate({
    {$match:{age:{$gt:20}}},
    {$group:
    {
    _id:'$gender',
    counter:{$sum:1}
    }
    }
    })

4. $project

  • 修改输入文档的结构,如重命名、增加、删除字段、创建计算结果
  • 例一:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    -- 查询学生的姓名、年龄
    db.集合名称.aggregate([
    {$project:
    {
    _id:0,
    name:1,
    age:1
    }
    }
    ])
  • 例二:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    -- 查询男生、女生人数,输出人数
    db.集合名称.aggregate([
    {$group:
    {
    _id:'$gender',
    counter:{$sum:1}
    }
    },
    {$project:
    {
    _id:0,
    counter:1
    }
    }
    ])

5. sort

  • 将输入文档排序后输出
  • 例一:

    1
    2
    3
    4
    5
    6
    7
    8
    -- 查询学生信息,按年龄升序
    db.集合名称.aggregate([
    {$sort:
    {
    age:1
    }
    }
    ])
  • 例二:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    -- 查询男生、女生人数,按人数降序
    db.集合名称.aggregate([
    {$group:
    {
    _id:'$gender',
    counter:{$sum:1}
    }
    },
    {$sort:
    {
    counter:-1
    }
    }
    ])

6. limit

  • 限制聚合管道返回的文档数
  • 例一:
    1
    2
    3
    4
    -- 查询2条学生信息
    db.集合名称.aggregate([
    {$limit:2}
    ])

7. $skip

  • 跳过指定数量的文档,并返回余下的文档
  • 例一:

    1
    2
    3
    4
    -- 查询从第三条开始的学生信息
    db.集合名称.aggregate([
    {$skip:2}
    ])
  • 例二:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    -- 统计男生、女生人数,按人数升序,取第二条数据
    db.集合名称.aggregate([
    {$group:
    {
    _id:'$gender',
    counter:{$sum:1}
    }
    },
    {$sort:
    {
    counter:1
    }
    },
    {$skip:1},
    {$limit:1}
    ])
    -- 注意:先写skip,再写limit

8. unwind

  • 将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值
  • 语法1

    • 对某字段值进行拆分
      1
      2
      3
      db.集合名称.aggregate([
      {$unwind:'$字段名称'}
      ])
  • 语法2

    • 对某字段值进行拆分
    • 处理空数组、非数组、无字段、null情况
      1
      2
      3
      4
      5
      6
      7
      8
      9
      db.集合名称.aggregate([
      {$unwind:
      {
      path:'$字段名称',
      preserveNullAndEmptyArrays:<boolean>#防止数据丢失
      }
      }
      ])
      -- preserveNullAndEmptyArrays为false的情况下,空数组、无字段、null的文档将被丢弃,若不想被丢弃,设为true

9. 索引

  1. 创建大量数据

    1
    2
    3
    for(i = 0; i < 100000; i++) {
    db.集合名称.insert({name:'test' + i, age:i})
    }
  2. 数据查找性能分析

    • 查找姓名为test10000的文档

      1
      db.集合名称.find({name:'test10000'})
    • 使用explain()命令进行查询性能分析

      1
      db.集合名称.find({name:'test10000'}).explain('executionStats')
  3. 建立索引

    • 创建索引

      1
      db.集合名称.ensureIndex({属性:1})
    • 1表示升序,-1表示降序

  4. 索引的命令

    • 建立唯一索引,实现唯一约束的功能

      1
      db.集合名称.ensureIndex({"name":1}, {"unique": true})
    • 联合索引,对多个属性建立一个索引,按照find()出现的顺序

      1
      db.集合名称.ensureIndex({name:1, age:1})
    • 查看文档所有索引

      1
      db.集合名称.getIndexes()
    • 删除索引

      1
      db.集合名称.dropIndexes('索引名称')